CO538 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 q6
2004 |
I was wondering that if we don't submit q6 before 4pm this afternoon, would it still be ok to submit it tomorrow ? As I might need more time to implement it.
The deadline is 4pm today (and this may be so that CAS can get the marking to us before the university closes). In the past we've operated a sliding-scale penalty for late submissions, where the penalty reaches 100% after 7 days; this will apply. Late submissions should be emailed directly to your seminar leader.
Please note that the model solutions will be made readable tomorrow, so that students may have something to read over the vacation, :). If you are submitting late, do not read the model solutions first (we can tell!).
Keywords: q6
I have modified my code below:
PROC sort.cell (CHAN OF NAME.NUMBER in, out) ... process body :
What I'm trying to do is grab the first name and store it in the "stored" variables, then go into a loop getting the other names, and comparing the name to "stored.name", and if it is equal it increases the stored mark, or it sends the name through the channel ("out"); if a "poison" is given it sets "ok" to false and sends the stored variables. It compiles fine but deadlocks when it runs.
I was wondering if the problem is in my "collate.marks" (I implemented it almost exactly how "sort.pump" was done) see below:
PROC collate.marks (CHAN OF NAME.NUMBER in, out) [max.diff.names] CHAN OF NAME.NUMBER c: PAR ... sort.cell processes :
Please help! I feel like I am cracking it but I have no real idea of where the problem is or why it isn't working!
These sort of questions are better targetted at your seminar leader -- since we can't post your solution on-line! The code is very nearly correct, except for one small thing. If you look at the sort-pump code, you'll see that each cell outputs its version of "poison" when it receives it. In your sort cells, receipt of "poison" triggers the output of the stored name, but the "poison" is never passed along! (so the next cell sees some incoming name, which it deals with, but no poison).
Keywords: q6
Should our program work over "nn_data.txt" or "small_results.txt" or both ?
Three test data files are provided in your exercises directory:
nn_tiny.txt nn_small.txt nn_data.txt
Your program should work over any of these files. The file "small_results.txt" is the result file produced from running my model answer on the "nn_small.txt" test data file. It's given so you can compare your results with mine. It has, of course, entirely the wrong format for an input data file for your program! The read.data process will handle it by simply outputting one poison message and terminating. So, actually, it would be a good test of your code to try using it that way! Your program should simplt terminate, after the display process has output its initial headings.
Keywords: q6
In "PROC q6" shouldn't "display" be wired to "(b, screen)" rather than "(a, screen)" ? well, according to the diagram anyway.
It should, yes, but you need to create "PROC collate.marks" and modify the code in "PROC q6" such that it matches the diagram. What goes inside "collate.marks" is up to you (but see the text in q6.occ).
The "q6" code body, given in the starter source code file, wires "read.data" directly to "display" -- you have to change that! The starter file was coded that way since it gives you something that is immediatley compileable and runnable on the test data files (although, of course, it won't produce the right results).
Keywords: q6
Do we need to paste the code for the sort pump or only include the modified code for the sort pump?
The sort pump was implemented as a pipeline of cells. The collate.marks process may also be implemented as a pipeline of cells ... but it has a different number of them.
So, you may find the code implementing sort pump useful as a guide for implementing collate.marks. But why should you want to paste in the code for sort pump in your solution?
Keywords: q6
Haviing major problems with Q6 -- the coding for cell, what I have done is:
[snip code]
Can you please tell me what's wrong with my code?
You can't ask questions like this! You must ask questions that are much more specific. You have made no attempt to analyse your code.
Ask yourself the question: what is right with my code?. This is not a silly question! For all of us, we must be able to justify why we write every single line ... what is it supposed to be doing ... what grounds do we have for thinking that that line will do it?!!
Only once we have done this, satisfying ourselves that our code is correct ... yet finding that it doesn't work ... can we try asking what is wrong with our code.
Keywords: q6
This may sound silly but there are no questions about using "CASE", could you please tell me a bit more about it and when it's used please. Thanks.
The "CASE" construct is much like C and Java's "switch". In occam, "CASE" can be used in three places: as a "switch" on some variable/expression; in tagged protocol definitions; and in tagged protocol input. There are plenty of examples of "CASE" usage -- see the past questions, course notes, the model answer to Q4 (its "keys" process) and this occam tutorial. It would also be neater to use a "CASE" for examining the result of a "compare.string" function, rather than an "IF", in Q6.
Keywords: tagged-protocol , case , q4 , q6
Concerning q6, we are required to compare two names -- one of which will be passed in through the "in" channel of a particular cell and the cell will itself contain the other.
In order to reference the incoming name, I understand that some temporary variables need to be used along with pattern matching in order to get the actual name from the "NAME.NUMBER" protocol.
I am having trouble referencing the name within the current cell to compare with this... do we need to create other procedures to separate out the components of "NAME.NUMBER" and to write back to them or is there a better way?
The whole point of a protocol structure such as NAME.NUMBER is that it presents its components to you very simply. There is absolutely no need to write procedures to separate them out ... that makes no sense ... they are already separated! Look at the code in display to see how to input the components into separate variables. The language does not allow you to input them into anything else (e.g. some structure from which you have to separate things).
You don't need any clever pattern matching! You just need the equal.string function, which is documented in your q6.occ starter file (and the "libsrc" course library directory) and has been explained in your seminar groups. Some, of course, will use the compare.string function instead (for producing a sorted list of collated names and marks).
Keywords: q6 , tagged-protocol
Hello. I think I have almost got a solution for q6, just that it's not terminating nicely even though I think I have dealt with the "poison" end marker by changing the state of the BOOL controlling the WHILE loop. Its just deadlocking.
If it's deadlocking it means that something hasn't terminated properly. Trace your code for a bit of data (i.e. several 'string; ...' variants) and then 'poison' to see where it might be getting stuck. Don't forget to pass on the 'poison'.
If you've got KRoC/Linux or KRoC/cygwin, compile with the "-d" flag (debugging) and the deadlocked process(es) will be reported.
Keywords: q6
Hello, I'm really struggling with q6. I have read all the q6 anon Q's and have got a start, but I don't know where to continue from there:
[snip code]
I don't know what do here; am I just suppsed to store the names in an array of array of bytes, iterate and check if they are equal to each other then update the marks ?
Please help! any step by step instructions would be immensely helpful (or anything at all).
You're actually on the right lines here. Yes, if you implement "collate.marks" as a single serial (sequential) process, then you'll need a large 2D array of BYTEs to hold the names (as well as other arrays to hold the marks, etc.). And yes, when a new name comes in, iterate over the array looking for a match. Programming this way is not nice, however. The other approach is to use parallelism, and to a large extent follow the logic of the sort-pump (except that sorting isn't the main task here).
This assessment has been extensively discussed in the last two seminars. Step-by-step instructions were presented there ...
Keywords: q6
Good afternoon; Just wanted to know if we can add additional procs to "q6.occ", or if everthing should be implemented within "collate.marks". I am referring to a cell process that takes in a "name.number", then makes some appropriate comparison/action.
Also, am I right in thinking the first and last cell cannot be replicated as they connect to non-cell channels. Finally, I am unsure how the replicator works/fits in -- do we create the maximum number of cells to correspond to the maximum number of different names, as we don't know in advance how many unique names there are. If so, isn't this inefficeient ? i.e. if we replicate 14 cells and there are only 2 different names, or is our main concern speed ?
Yes, you can add additional PROCs to "q6.occ". You can declare such PROCs either above "PROC collate.marks", or inside it -- up to you (but outside and above is usually clearer).
As replication goes, yes, you are right in that the first and last cells in the pipeline connect slightly different -- these connect to the external channels. It would be possible to arrange this differently, with all the cells generated using a replicated PAR, but then you'd need two "id" type processes to connect the two end channels to the external channels. Separating out the first and last cells is just a bit simpler.
As far as efficiency is concerned, the use of unnecessary cells isn't a problem. Occam is extremely light-weight in its implementation: a sort-pump containing 500,000 processes will get data through it in under 1 second on most systems. The current performance "micro-benchmark" for communication/context-switch time is under 100ns (on an 800 MHz P3) -- meaning that over 10,000,000 processes can be scheduled per second on this hardware.. :-). Compare this with the threading support offered by languages such as Java -- you'd be lucky to get 1000 parallel processes to work (either at all, or in useful time).
Keywords: q6
I "think" I am nearly there with q6 I just have one problem left. If all the names are the same size then my code works fine :-). However if the names are different sizes it goes a bit wonky. Say I have:
Mandy 551 Mandy 976 Sonya 577 Hubert 969 Mandy 127
And I have "[INT]BYTE temp:", where the max length for a name is 8 and a space is represented as ~, "temp" would hold values something like this:
1) Mandy~~ 2) Mandy~~ 3) Sonya~~ 4) Hubert~ 5) Mandyt~
The `t' of "Hubert" is not being cleard when I push "Mandy" into it. Well thats all I can come up with why it is not working. How would I clear a string to make it all spaces?
Any tips would be great!
To clear all the elements of a byte array to spaces is trivial (and obvious!):
SEQ i = 0 FOR SIZE my.array my.array[i] := ' '
But it sounds like you're not calling "make.string" correctly. Whenever you read from the tagged protocol channel into the byte array (along with the number of bytes, say "count", communicated for the name and the associated mark), only the first "count" elements of the array are changed -- the rest are not touched. You must call the "make.string (name, count)" procedure, where "name" is the name of the byte array. This clears any bytes left over in "name" to zero (the ASCII NUL character) -- that is all bytes apart from the first "count" elements. That will erase your left-over `t~'.
Keywords: q6 , string-handling
Two questions in one here. First of all waht is a counted array?
Second currentley I am trying to create a cell for q6. All I am trying to do at the moment is read in the protocol then just output what ever comes in. So just like the ID in the lego.occ. Looking at Fred's Occam tutorial as the protocol is a tagged-protocol I need to do something like:
PROC cell(CHAN OF NAME.NUMBER in, out) in ? case string; INT::[]BYTE; INT ... do something poison ... do something else :
How do I read in the "string; INT::[]BYTE; INT" and the "poison" into a varible.
First question: section 7.4 of the "occam2 Checklist". Also, slides 5-45 through 5-47.
Second question: section 7.3 of the "occam2 Checklist". Also, slides 10-18 through 10-21 (in the Powerpoint Chapter 10, these are currently slides 20 through 25).
Please look through your notes before asking questions here!
You say the q6 program can be compiled and the read.data sends to straight to display. Then why is there no output displayed?? Shouldn't it display something as it's getting the correct protocol and data within it.
Well, I just compiled your q6.occ file on raptor and ran it:
raptor% ./q6 < nn_tiny.txt Name Mark ---- ---- Fred -10 Alison 944 Fred 720 George 628 Alison 20 Peter 331 raptor%
So, it displays output for me! I've left the q6 executable in the course exercises directory, so you can check ... although it's trivial to compile the starter file yourself in your own directory.
Keywords: q6
Just finished Q6. It outputs the same table as given in small_result.txt. One problem though - it deadlocks - most probably because the cells are awaiting more input. Is it ok to leave the program deadlocked once it has finished?
Your solution to Q6 must not deadlock after processing all the data. That's the whole point of sending through the poison message -- so that each process knows when its job is done and can terminate! Look at the given processes read.data and display. Once they have processed the poison, they terminate. For your collate.marks, processing the poison means outputting all the collated names and marks and, then, outputting the poison ... and then it should terminate ... it should not loop back and await more input!
Keywords: q6
In an previous anonymous question someone asked how to compare strings. The answer said to pass these BYTE arrays through the "make.string" function and then use "compare.string". However, I get the error:
make.string is not a function
Is this a provided function or do we have to make it ourselves ?
"make.string" is provided, but it's not a function -- it's a procedure. It adjusts the BYTE-array given to it as a parameter so that the string can be used with the other string functions -- which are really functions (e.g. "compare.string" and "equal.string"). The the answer to Question 50 (2003) for a code example on how to use it.
Keywords: q6 , string-handling
How can I make a simple routine that forwards data of `NAME.NUMBER' ? I'm trying:
SEQ INT size: in ? size::n; m out ! size::n; m
And have also tried:
SEQ INT size: in ? string; size::n; m out ! string; size::n; m
But I'm getting errors such as "string is not delcared" and "Simple input is not allowed on a channel with a tagged protocol".
I have looked over the chapter 10 pages, but it doesn't cover protocol input for just one type of input. I assume you don't need to use another CASE here.
The first problem is the scope of `size'. See the answers to Question 19 (2004), Question 29 (2000) and Question 3 (2000).
As for the tagged-protocol input, why do you `assume you don't need to use another CASE here'? Slide 10-21 in the printed notes (chapter 10, slide 25, in the Powerpoint) and section 7.2 of the "occam2 Checklist" show you the syntax for this:
in ? CASE INT size: string; size::n; m out ! string; size::n; m
If you don't specify the `poison' case, that's fine ... but if a `poison' arrives, your process will STOP (i.e. crash!).
So, the above is what the code fragments in your question should have been, assuming that your variables `n' and `m' have also been defined somewhere (e.g. just before or after your `size' declaration). However, this code fragment only forwards `string' variants of the `NAME.NUMBER' protocol -- not all data variants as the wording in your question implies. In your solution to Q6, you will need to be handling all variants of `NAME.NUMBER'.
However, here's another bit of occam. When inputting a `CASE' protocol, if you are sure that only one variant message will arrive, there is a special syntax ... but you still have the `CASE' keyword and the relevant tag name. For your example, the shortcut code would have been:
INT size: SEQ in ? CASE string; size::n; m out ! string; size::n; m
though it's not actually any shorter (because of the need for the `SEQ')!
2003 |
On Q6 am I right in thinking that both the make.string and compare.string are done inside the individual cells?
Is it also right that when the first `NAME.NUMBER' is passed to the cells from collate.marks the tempoary string for holding that cells name is empty and it just takes the first name its given as its cell name from now on?
If Im right in my understanding, then the names will not come out in alphebetical order will they?
To get the names and thier respective marks out in alphabetical order, will I need to collect them in an array once poison has been called and then compare them again?
Yes, make.string and compare.string should be done inside the cell processes.
On your second question, yes, the cell is initially `empty'. When the first name/mark input arrives, the cell should store it. As a point, collate.marks shouldn't do anything (computational or communication) if you're using a pipeline of cell processes -- it just sets up the pipeline.
On your third point, yes, the output will not be sorted (unless the input was).
Sorting the names alphabetically is not required for this assignment -- it's just nice. However, collecting data in an array and sorting there is definitely not the right way, unless you didn't use a pipeline of cells. See the lecture notes on the `sort-pump'.
Keywords: q6
I'm really having trouble trying to output all the results,
I looked at the previous questions and got the idea for a toggle but came with problem that to set a toggle it will have to send a poison first each time, because the contents of that cell and would end up with nothing being outputted
I'm afraid I don't fully understand your question. What do you mean by `toggle' ?
The general behaviour of the `read.data' process is:
That is the order of things which the `display' process expects. I.e. it does:
Thus, any processes that you put inbetween these should (must) follow the same pattern of communication.
Keywords: q6
is an empty string represented as ""
e.g. `equal.string(name,"")' would check if the name varible was empty
Yes, that comparison will return TRUE, if at some point, previously, this happened:
make.string (name, 0)
Keywords: q6 , string-handling
For q6, is it ok for the program to terminate by deadlocking?
i.e. when all of the data has been read in, processed and outputted to the screen, should the program end with the error message:
program deadlocked no processes to run
Or do we need to terminate the program in some other way?
The program should terminate cleanly, i.e. without deadlock. Using the poison tag, this should not be too hard to achieve. Just arrange for each process to exit its loop when it receives poison, tidy up and output poison (if it has an output channel) and finish its code!
Marks will be lost if your solution simply deadlocks when done.
Keywords: q6
After using `make.string' on the BYTE arrays so I can compare them, is it ok to continue using them as BYTE arrays afterwards, or is there something I need to do to turn them back ?
They're still BYTE arrays (adjusted slightly to allow the string utilities to work), so yes, continue using them in that way.
Keywords: q6
I can't figure out the best way to have all the values read out once the cells are full (using the pipeline implementation). The way I thought of doing was to have the `poison', marking the end of the input, sent along to each cell along the pipeline. This would cause a toggle in each cell to switch meaning that the cell would output the `poison' to the next cell and then output what it contains and then outputs everything it recieves from then on. Only problem is that doing this means the `poison' is moved to the end of the queue to the front and outputted first into the `display', meaning no outputs are put on screen.
Could you give me a few hints as to a way I could trigger all cells to start outputting their contents without moving the `poison' from being the last output? Sorry if this isnt clear!
As you suggest, poison should be the last thing happening. The `read.data' process only outputs the poison after it has output all the data. Your cells should follow suit -- the `poison' tag should only be sent once any data in the cell has been sent (effectively the reverse of what you appear to be doing at the moment).
Am I correct in thinking the command line to run the program would be along the lines of (assuming `data.txt' is the data going in):
data.txt | q6
?
Not quite, see the answer to Question 52 (2000). What you probably meant for the above was:
raptor$ cat data.txt | ./q6
Keywords: q6 , keyboard-input
Are there any network diagrams that we need to hand in as well for q6? The q6 PROC is already drawn out in the file, and the `collate.marks' changes depending on the max number of names.
No, you do not need to submit any additional diagrams for this assessment.
Keywords: q6
When trying to implement a cell I get the error:
Error-oc-q6.occ(160)- Simple input is not allowed on a channel with a tagged protocol
on:
in?string; length::name; mark
See the answer to Question 53 (2003)
This is probably stupidly simple but my mind has gone blank. I've got an input of type NAME.NUMBER in q6 coming into my cell. I've taken the first INT and put it into a variable, now I want to take the next so many inputs (the number represented by the int) which is the name and put them into a list of char variable. How do I do it? Is there a line of code which will add one char to the end of a list?
I think there is some confusion here. Just for the record, occam has neither char or list types. What it does have are BYTEs and arrays.
You say that you read the first INT into a variable, but I can't see how that would compile -- there would be a protocol mismatch (or other) error. The purpose of a counted-array communication/protocol (as described by `INT::[]BYTE') is to communicate both a length and that number of array elements. Thus, you do not need to do this yourself; all you need do is ensure that the inputting side's array is large enough to hold anything the outputter might send (a run-time error occurs if this is not the case).
As a fairly basic (!) example, consider:
#USE "course.lib" PROC hello (CHAN OF BYTE kyb, scr, err) PROTOCOL TEST IS INT::[]BYTE: CHAN OF TEST c: PAR --{{{ output process VAL []BYTE str IS "Hello, counted-array world!*n": c ! (SIZE str)::str --}}} --{{{ input (and report) process [64]BYTE tmp.str: -- should be large enough INT tmp.len: SEQ c ? tmp.len::tmp.str out.string ("The message was: ", 0, scr) out.string ([tmp.str FOR tmp.len], 0, scr) --}}} :
See also the answer to Question 53 (2003).
For q6 do we need some form of end marker ? like the sort pump. If so how do we represent an end marker?
Yes, you do need an `end-marker'. It is provided for you, however -- as the `poison' tag. The `read.data' process will output this once it has finished reading all the names (before terminating). The `display' process, when it receives this tag, also terminates.
See also the answers to Question 53 (2000) and Question 61 (2000)
How do we view the `course.lib' file ? I have tried opening in eXceed (with and without gvim). What do we open it with ? Also, what do we use the processes for strings from the `course.lib' file for ? Thank you in advance.
You can't view the file `course.lib' sensibly. It's a form of Transputer library file (like a Java .jar I guess) -- only useful to the compiler and associated tools.
The source code that makes up this library is readily available, on raptor, in the directory:
/usr/local/courses/co516/libsrc/
In response to your second question, you need the string PROCs and FUNCTIONs in order to manipulate the BYTE arrays -- occam does not have a built-in `STRING' type, so like C, we make do with arrays of BYTEs.
Arrays in occam are generally fixed-size, but the string contained inside them may well be smaller (as is generally the case in q6). The string utilities deal with this nicely, so you don't have to.
For specific information on the string utilities, read the documentation provided in the `string.occ' file (in the directory mentioned above).
The answer to Question 19 (2001) might also be useful.
Keywords: q6 , course-library
Hi, a question about Q6:
I want to store the in channel. I have written the following line:
in ? string; temp.name.length::temp.name; temp.score
The compiler says it that string has not been defined. Yet in the `read.data' process, `string' is used and is not defined within the process. It doesn't work without the string either as it the compiler says:
Simple input is not allowed on a channel with a tagged protocol
Any help please?
The second of the two errors is more meaningful -- the `in' channel is of a tagged-protocol. The protocol in this case is `NAME.NUMBER', defined in q6.occ as:
PROTOCOL NAME.NUMBER CASE string; INT::[]BYTE; INT -- string; name; number poison -- sent, and only sent, as the last message :
The `string' referred to is the one in the above protocol definition.
There are two forms of tagged input in occam. The first allows for multiple CASEs; the second for a specific CASE only. For example, from the `display' PROC (in q6.occ):
in ? CASE --{{{ poison poison ok := FALSE --}}} --{{{ string; name; number --{{{ variables [max.name.length]BYTE name: INT name.length: INT mark: --}}} string; name.length::name; mark SEQ out.string ([name FOR name.length], max.name.length, out) out.int (mark, max.name.length, out) out.string ("*c*n", 0, out) --}}}
This shows the first form of tagged input -- where the `display' process handles both tags. The second form is just for a single tag, but not to dissimilar:
--{{{ variables [max.name.length]BYTE name: INT name.length, mark: --}}} SEQ in ? CASE string; name.length::name; mark ... do something
Also see the answers to Question 26 (2002) and Question 18 (2001).
Referrers: Question 57 (2003) , Question 58 (2003) , Question 59 (2003)
For q6 i have just tried compiling my code and the compiler says
no PROC or FUNCTION declared in sc module Incomplete program - no entry point
Whats all this about?
I have checked that their is a main function (i.e. q6 PROC has not been touched) i have only added a PROC and not done anything else.
The most likely reason for this error is a missing colon `:' at the end of a PROC definition. PROC definitions should have the form:
PROC name (formal parameters) ... body :
Referrers: Question 51 (2003)
I'm stuck on q6. My program deadlocks and I don't know why. I have managed to work out that it is something to do with my `cell' procedure, and also it appears to me that the `string.equals' procedure doesn't work in my cells. Any help would be great thanks.
[snip code]
Questions such as this are not easily answered in this public forum. Consider emailing your seminar leader.
However, in response to your query, when using `equal.string', etc., you must first ensure that `make.string' has been used on the string. These strings are not really strings -- they are arrays of BYTEs. `make.string' adjusts the array so that comparisons, etc. are based on the length of the `string', not the size of the array.
Keywords: q6 , string-handling
Referrers: Question 50 (2003)
I have written my `q6' using a pipeline of cells with the cells written in a similar style to the `display' PROC (with IF statements to decide whether to send the incoming values on).
It compiles with no problems, but when I run it I get:
KROC: Range error / STOP executed (signal 4) KROC: Fatal error code 1, core dumped Abort (core dumped)
What is the likely reason for this ? I've checked through my code and it seems to be fine.
Please refer to Question 30 (2003).
Keywords: q6 , range-error
2002 |
In the main cycle of Display in q6 it has the line:
string; name.length::name; mark
Could you please explain what it is doing and how to use it?
See the answer to Question 26 (2002).
Keywords: q6
I get this funky error and don't know what it means and how to solve it. Any tips would be appreciated.
Simple input is not allowed on a channel with a tagged protocol
It happened when I tried to store a NAME.NUMBER using:
in ? nameTemp; scoreTemp
NAME.NUMBER is a tagged - sometimes called a CASE or variant - protocol. See slide 10-21, section 7.3 of the Checklist paper or the display process in q6.occ, for how to input from a channel carrying such protocool. It should be somelthing like:
in ? CASE ... local delarations string; length::nameTemp; scoreTemp ... response to name-mark code poison ... response to poison code
Referrers: Question 53 (2003) , Question 27 (2002)
2001 |
For Q6, if I have two strings called a and b and I want to use the compare.string function on them, how do I do it? Is it something like:
compare.string (a, b)
Also, if I get back string.less or string.more, which of the two strings is being referred to as smaller or bigger than the other?
Yes to your first question. Make sure you have read the documentation in libsrc/string.occ, which is part of the course library and which contains the string handling routines. Most important is that functions like compare.string (etc.) do not work unless the BYTE arrays on which they operate have first been processed by make.string.
To your second question, if compare.string (a, b) returns string.less, then a is less than b. That was meant to be obvious ... if you were at all unsure, a glance at the source code would have confirmed this ...
Note: if others have further questions about this assignment, please first refer to last year's Question 51 (2000) onwards.
Keywords: q6 , string-handling
Referrers: Question 50 (2003) , Question 54 (2003)
I keep getting the error:
Simple input is not allowed on a channel with a tagged protocol ...
when I just try to connect the collate process between the read.data and display in Q6. What do you think I should do?
You should not try to do simple input on a channel with a tagged protocol! Tagged (or CASE) protocols are explained in Section 7 of The occam Checklist and in slides 10-18 through 10-22 (which have been talked though in lectures). See also the code in the display process given in your q6.occ started file.
Referrers: Question 53 (2003)
Is it alright for the output from my q6.occ to list the names in a different order to those listed by your model a6 answer?
Yes. The order of the names does not matter. Of course, each name should only appear once and the total marks for that name should be alongside it. As an additional exercise, it would be nice to list the names in alphabetical order ... but there are no extra marks for that!
Keywords: q6
2000 |
A note on the diagrams needed in our submission for question 6. The diagram for q6.occ is already in the file - so obviously we don't have to reproduce that. And the diagram for cells is so small and just shows the obvious. Do we definitely have to include a diagram?
No - for the reasons you state and for this submission only, you do not have to include a data-flow diagram.
Further, to save paper, you may delete the documentation I supplied from the program listing you print out. Make sure you still print a complete program and include your own documentation for the modifications you have made.
Could you please help me with reading in the protocols for Q6. From looking at the notes on 10-21, I have worked out it is a tagged protocol. Here is the code that I have written:
SEQ ok := TRUE WHILE TRUE in ? CASE INT size: string; size::name; mark poison ok := FALSE
But I get errors with incorrect indentation. I'm presuming that this is not the problem. And there is something wrong with what I have written. If I comment out the string line, it compiles - but with it in, it does not. I'm not sure how to read in the string tag. Is what I have written completly wrong? Any pointers please!
Well, I should just refer you to the answers to Question 57 (2000) and Question 53 (2000) ...
However, each tagged variant in a CASE input requires a response - the action to be performed if you get that variant. That response is written in some code that has to be indented, as usual, just after the line inputting that variant. In the above, you have such a line for the poison variant, but not for the string one. So, the compiler correctly complains that the line following that string variant is incorrectly indented - it should be your response to the input. For example:
SEQ ok := TRUE WHILE TRUE in ? CASE INT size: string; size::name; mark SKIP -- >>>>>>>>> maybe a fuller response should be here ... poison ok := FALSE
Keywords: q6 , incorrect-indentation
Hi. If we receive a poison should we output it? It is not too clear in the question how the program should terminate. Could you clarify please.
The higher-level protocol used on NAME.NUMBER channels is that, most of the time, only string variants flow. A poison variant only gets sent once and is the last item to be sent down the channel.
A process receiving poison should take that as a hint to die, tidying up any outstanding business first. That business might include outputting more string variant(s) on its output and, finally, a poison variant - so that the next process in the pipeline knows that it, also, should terminate.
You should notice that the given processes, read.data and display, both behave in this way. So should your processes. Then, all the processes in your system will terminate cleanly when all the data has been processed and your whole program will end.
All of the above will have been discussed in your seminar groups earlier this term.
Referrers: Question 55 (2003)
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!!
See the answer to Question 56 (2000).
Keywords: q6
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?
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
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?
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)
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?
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)
What does the process file.in.token (from file_in.occ) do with regards to question 6?
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
What extra marks will we get if we implement the sorting of the names in question 6?
None - see the answer to Question 51 (2000). But your reward will be a better understanding and greater confidence!
Keywords: q6
For question 6, what value is poison (so that I can test for it)?
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.
Referrers: Question 55 (2003) , Question 57 (2000) , Question 62 (2000)
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?
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)
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?
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)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License. |