I am a beginner with promela and SPIN. I have a small code in promela but I do not understand why I have the error mentioned below:
chan config =[16] of {short};
bool get_type = false;
short car_type = 4;
active proctype control() {
start:
do
:: get_type == false ->
config!car_type;
printf("type sent");
:: printf("type not received");
od
}
active proctype robot() {
sleep:
config?car_type ->
get_type = true ;
printf("type received= %d", car_type);
}
Error:
using statement merging
1: proc 0, no matching stmnt 91
#processes: 2
1: proc 1 (robot:1) mytest.pml:16 (state 1)
1: proc 0 (control:1) mytest.pml:7 (state 5)
2 processes created
Exit-Status 0
Related
I understand that the parameters α and β can be used in the Hockney model to represent latency and bandwidth in peer to peer communications with m representing the message size. For example:
T(m) = α + β · m
I have been trying to model some OpenMPI algorithms using this technique and can't figure out this following algorithm for MPI_Scatter:
int
ompi_coll_base_scatter_intra_linear_nb(const void *sbuf, int scount,
struct ompi_datatype_t *sdtype,
void *rbuf, int rcount,
struct ompi_datatype_t *rdtype,
int root,
struct ompi_communicator_t *comm,
mca_coll_base_module_t *module,
int max_reqs)
{
int i, rank, size, err, line, nreqs;
ptrdiff_t incr;
char *ptmp;
ompi_request_t **reqs = NULL, **preq;
rank = ompi_comm_rank(comm);
size = ompi_comm_size(comm);
/* If not root, receive data. */
if (rank != root) {
err = MCA_PML_CALL(recv(rbuf, rcount, rdtype, root,
MCA_COLL_BASE_TAG_SCATTER,
comm, MPI_STATUS_IGNORE));
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
return MPI_SUCCESS;
}
if (max_reqs <= 1) {
max_reqs = 0;
nreqs = size - 1; /* no send for myself */
} else {
/* We use blocking MPI_Send (which does not need a request)
* every max_reqs send operation (which is size/max_reqs at most),
* therefore no need to allocate requests for these sends. */
nreqs = size - (size / max_reqs);
}
reqs = ompi_coll_base_comm_get_reqs(module->base_data, nreqs);
if (NULL == reqs) {
err = OMPI_ERR_OUT_OF_RESOURCE;
line = __LINE__; goto err_hndl;
}
err = ompi_datatype_type_extent(sdtype, &incr);
if (OMPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
incr *= scount;
/* I am the root, loop sending data. */
for (i = 0, ptmp = (char *)sbuf, preq = reqs; i < size; ++i, ptmp += incr) {
/* simple optimization */
if (i == rank) {
if (MPI_IN_PLACE != rbuf) {
err = ompi_datatype_sndrcv(ptmp, scount, sdtype, rbuf, rcount,
rdtype);
}
} else {
if (!max_reqs || (i % max_reqs)) {
err = MCA_PML_CALL(isend(ptmp, scount, sdtype, i,
MCA_COLL_BASE_TAG_SCATTER,
MCA_PML_BASE_SEND_STANDARD,
comm, preq++));
} else {
err = MCA_PML_CALL(send(ptmp, scount, sdtype, i,
MCA_COLL_BASE_TAG_SCATTER,
MCA_PML_BASE_SEND_STANDARD,
comm));
}
}
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
}
err = ompi_request_wait_all(preq - reqs, reqs, MPI_STATUSES_IGNORE);
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
return MPI_SUCCESS;
err_hndl:
if (NULL != reqs) {
/* find a real error code */
if (MPI_ERR_IN_STATUS == err) {
for (i = 0; i < nreqs; i++) {
if (MPI_REQUEST_NULL == reqs[i]) continue;
if (MPI_ERR_PENDING == reqs[i]->req_status.MPI_ERROR) continue;
if (reqs[i]->req_status.MPI_ERROR != MPI_SUCCESS) {
err = reqs[i]->req_status.MPI_ERROR;
break;
}
}
}
ompi_coll_base_free_reqs(reqs, nreqs);
}
OPAL_OUTPUT((ompi_coll_base_framework.framework_output,
"%s:%4d\tError occurred %d, rank %2d", __FILE__, line, err, rank));
(void)line; /* silence compiler warning */
return err;
}
So far I understand that from looking at the code that the model should be
T(NP, m) = (NP − 1) · (α + m · β).
With NP being the number of processes (As Scatter distributes using all processes apart from the root).
This does not account for the use of non-blocking sends that are send using MPI_Isend. (on the condition found in the code snippet) I am unsure of how to account for both the non-blocking and blocking sends using simply the Hockney Model.
Any help would be very much appreciated as non of the papers that I have read on the subject seem to explain the process well.
First of all, the source file mentions that this implementation is probably only for small numbers of processes: for larger numbers you probably want to do something treewise. Next, the max_reqs parameter controls how many isend calls you do before a blocking send call. So the running time of this algorithm would be equal to the number of times you do a blocking send. In an ideal world. In practice, non-blocking sends still have to be serialized out.
My best guess is that this algorithm can handle the case where there are multiple network cards or multiple ports per network card. If you can send 4 messages at a time (physically!) then this code sets up 3 non-blocking & 1 blocking send, and when the blocking send has gone through, your network ports are ready for the next batch of messages.
/**
* Example:
* var li = ListNode(5)
* var v = li.`val`
* Definition for singly-linked list.
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/
class Solution {
fun mergeTwoLists(l1: ListNode?, l2: ListNode?): ListNode? {
var head : ListNode?
var tail: ListNode?
var firstPointer : ListNode? = l1
var secondPointer : ListNode? = l2
while( firstPointer != null || secondPointer != null){
var next : ListNode?
if (firstPointer == null || secondPointer == null){
if (secondPointer != null){
next.val = secondPointer.val
secondPointer = secondPointer.next
}else {
next.val = firstPointer.val
firstPointer = firstPointer.next
}
}else if(firstPointer.val <= secondPointer.val) {
next.val = firstPointer.val
firstPointer = firstPointer.next
}else if(secondPointer.val <= firstPointer.val ){
next.val = secondPointer.val
secondPointer = secondPointer.next
}
if (head == null){
head = next
tail = next
}else {
tail.next = next
tail = next
}
}
return head
}
}
getting a lot of compile time errors
Line 22: Char 29: error: expecting property name or receiver type
next.val = secondPointer.val
^
Line 25: Char 29: error: expecting property name or receiver type
next.val = firstPointer.val
^
Line 28: Char 39: error: type expected
}else if(firstPointer.val <= secondPointer.val) {
^
val is a keyword in kotlin. If you want to use it as a name of a field, you need to wrap it into backticks: secondPointer.`val`, firstPointer.`val` (actualy, code example in the comment before your code shows that).
Well, I don't know Kotlin well, but from my perspective this might be the problem:
var next : ListNode?
Because you define a variable, but it is still null.
When you then try to access its field val you can't, because null has no such field.
I've come across a programming question at reddit (Take a look at the link for the question)
This was one the solutions in Python:
s="112213"
k=2
result=0
for i in range(len(s)):
num_seen = 0
window = {}
for ind in range(i, len(s)):
if not s[ind] in window:
num_seen += 1
window[s[ind]] = 1
else:
window[s[ind]] += 1
if window[s[ind]] == k:
num_seen -= 1
if num_seen == 0:
result +=1
elif window[s[ind]] > k:
break
print(result)
I've tried to port this solution into Raku and here is my code:
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s {
my $seen = 0;
my %window;
for #s[$_..*] {
if $^a == %window.keys.none {
$seen++;
%window{$^a} = 1;}
else {
%window{$^a} += 1;}
if %window{$^a} == $k {
$seen--;
if $seen == 0 {
$res++;} }
elsif %window{$^a} > $k {
last;}}}
say $res;
It gives this error:
Use of an uninitialized value of type Any in a numeric context in a block at ... line 13
How to fix it?
I don't feel that's a MRE. There are too many issues with it for me to get in to. What I did instead is start from the original Python and translated that. I'll add some comments:
my \s="112213" .comb; # .comb to simulate Python string[n] indexing.
my \k=2;
my $result=0; # result is mutated so give it a sigil
for ^s -> \i { # don't use $^foo vars with for loops
my $num_seen = 0;
my \window = {}
for i..s-1 -> \ind {
if s[ind] == window.keys.none { # usefully indent code!
$num_seen += 1;
window{s[ind]} = 1
} else {
window{s[ind]} += 1
}
if window{s[ind]} == k {
$num_seen -= 1;
if $num_seen == 0 {
$result +=1
}
} elsif window{s[ind]} > k {
last
}
}
}
print($result)
displays 4.
I'm not saying that's a good solution in Raku. It's just a relatively mechanical translation. Hopefully it's helpful.
As usual, the answer by #raiph is correct. I just want to do the minimal changes to your program that get it right. In this case, it's simply adding indices to both loops to make stuff clearer. You were using the context variable $_ in the first, and $^a in the second (inner), and it was getting unnecesarily confusing.
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s -> $i {
my $seen = 0;
my %window;
for #s[$i..*] -> $c {
if $c == %window.keys.none {
$seen++;
%window{$c} = 1;
} else {
%window{$c} += 1;
}
if %window{$c} == $k {
$seen--;
if $seen == 0 {
$res++;
}
} elsif %window{$c} > $k {
last;
}
}
}
say $res;
As you see , besides trying to indent everything a bit more properly, the only additional thing is to add -> $i and -> $c so that loops are indexed, and then use them where you were using implicit variables.
I have this program which creates file on USB stick. The problem is it is only saving one line (rewriting same line). I would need after each cycle it would write the data to new line . I think it has to do something with offset I need to calculate offset so it doesn't start from 0 every time. Here is the part of the code
10: DevLink_0.enable := TRUE;
DevLink_0.pDevice := ADR('Disk');
DevLink_0.pParam := ADR(cesta_k_USB);
DevLink_0();
IF DevLink_0.status =0 THEN
step :=20;
END_IF
20: FileCreate_0.enable := TRUE;
FileCreate_0.pDevice := ADR('Disk');
FileCreate_0.pFile := ADR('results.csv');
FileCreate_0();
IF FileCreate_0.status = 0 THEN
identification_file := FileCreate_0.ident;
offset :=0;
step :=30;
END_IF
IF FileCreate_0.status = fiERR_EXIST THEN
step :=25;
END_IF
25: FileOpen_0.enable := TRUE;
FileOpen_0.pDevice := ADR('Disk');
FileOpen_0.pFile := ADR('results.csv');
FileOpen_0.mode := FILE_W;
FileOpen_0();
IF FileOpen_0.status = 0 THEN
identification_file := FileOpen_0.ident;
offset := FileOpen_0.filelen;
step := 30;
END_IF
30: data:=INT_TO_STRING(y);
data:=INSERT(data,'$r$n',LEN(data));
FileWrite_0.enable := TRUE;
FileWrite_0.ident := identification_file;
FileWrite_0.pSrc := ADR(data);
FileWrite_0.len := LEN(data);
FileWrite_0.offset := offset;
FileWrite_0();
IF FileWrite_0.status = 0 THEN
step :=40;
END_IF
40: FileClose_0.enable := TRUE;
FileClose_0.ident := identification_file;
FileClose_0();
IF FileClose_0.status =0 THEN
IF save = FALSE THEN
step :=50;
ELSE
step := 25;
END_IF
END_IF
50: DevUnlink_0.enable := TRUE;
DevUnlink_0.handle := DevLink_0.handle;
DevUnlink_0();
IF DevUnlink_0.status =0 THEN
stav:= 0;
END_IF
As already mentioned in a comment, you will need to set the offset in the FileWrite FUB correspondingly.
I do this usually with the FileInfo FUB Guid 6eaf42f0-4ce5-44b7-95cb-275ae1c2fac5 in the AS help. It will tell you if the file exists already and also which size it has.
If it exists, the next step would be FileOpen, otherwise FileCreate.
Recently I have created a small project on GitLab which is, among other things, also appending a line to a file: https://gitlab.com/kirni/bur_robotic_sample/blob/master/bur_robotic_sample/Logical/Libraries/TeachLib/Teach.c
The code is in C, but I am sure you get the idea.
case stTEACH_INFO:
/*setup fub*/
this->fbInfo.enable = 1;
this->fbInfo.pDevice = (UDINT)inst->szDevice;
this->fbInfo.pName = (UDINT)inst->szFile;
this->fbInfo.pInfo = &this->Info;
//call fub
FileInfo(&this->fbInfo);
//fub is done..
if(this->fbInfo.status != ERR_FUB_BUSY)
{
//file exists -> open it and append code
if(this->fbInfo.status == ERR_OK)
{
//start writing to the end of the file
this->Offset = this->Info.size;
//open existing file
this->Step = stTEACH_OPEN;
}
//file does not exist -> create it and insert code
else if(this->fbInfo.status == fiERR_FILE_NOT_FOUND)
{
//start writing at the beginning of the file
this->Offset = this->Info.size;
//crete new file
this->Step = stTEACH_CREATE;
}
//error
else
{
//set error status and goto error state
inst->Status = this->fbInfo.status;
this->Step = stTEACH_ERROR;
}
//disable fub
this->fbInfo.enable = 0;
FileInfo(&this->fbInfo);
}
break;
case stTEACH_CREATE:
/*setup fub*/
this->fbCreate.enable = 1;
this->fbCreate.pDevice = (UDINT)inst->szDevice;
this->fbCreate.pFile = (UDINT)inst->szFile;
//call fub
FileCreate(&this->fbCreate);
//fub is done..
if(this->fbCreate.status != ERR_FUB_BUSY)
{
//success
if(this->fbCreate.status == ERR_OK)
{
this->Ident = this->fbCreate.ident;
//open existing file
this->Step = stTEACH_WRITE;
}
//error
else
{
//set error status and goto error state
inst->Status = this->fbCreate.status;
this->Step = stTEACH_ERROR;
}
//disable fub
this->fbCreate.enable = 0;
FileCreate(&this->fbCreate);
}
break;
case stTEACH_OPEN:
/*setup fub*/
this->fbOpen.enable = 1;
this->fbOpen.pDevice = (UDINT)inst->szDevice;
this->fbOpen.pFile = (UDINT)inst->szFile;
this->fbOpen.mode = fiREAD_WRITE;
//call fub
FileOpen(&this->fbOpen);
//fub is done..
if(this->fbOpen.status != ERR_FUB_BUSY)
{
//success
if(this->fbOpen.status == ERR_OK)
{
this->Ident = this->fbOpen.ident;
//open existing file
this->Step = stTEACH_WRITE;
}
//error
else
{
//set error status and goto error state
inst->Status = this->fbOpen.status;
this->Step = stTEACH_ERROR;
}
//disable fub
this->fbOpen.enable = 0;
FileOpen(&this->fbOpen);
}
break;
case stTEACH_WRITE:
/*setup fub*/
this->fbWrite.enable = 1;
this->fbWrite.ident = this->Ident;
this->fbWrite.offset = this->Offset;
this->fbWrite.pSrc = this->szLine;
this->fbWrite.len = this->Lenght;
//call fub
FileWrite(&this->fbWrite);
//fub is done..
if(this->fbWrite.status != ERR_FUB_BUSY)
{
//success
if(this->fbWrite.status == ERR_OK)
{
this->Ident = this->fbWrite.ident;
//Write existing file
this->Step = stTEACH_CLOSE;
}
//error
else
{
//set error status and goto error state
inst->Status = this->fbWrite.status;
this->Step = stTEACH_ERROR;
}
//disable fub
this->fbWrite.enable = 0;
FileWrite(&this->fbWrite);
}
break;
However this should also work with the filelen output of the FileOpen FUB - just the way you did it. I would suggest, that you set a brakepoint just before writing and check if the offset is set on the FUB properly.
I would also recommend, that you call each FUB after it was done, again with enable:=0 (like I did in my sample) i.e. disabling it. Some FUBs only update their inputs parameters on a positive edge on the enable, execute, start, etc. input command.
I hope this helps!
This does what I'd expect. fib(13) returns 233.
sub fib(Int $a --> Int) {
return 0 if $a == 0;
return 1 if $a == 1;
return fib($a -1) + fib($a -2);
}
my $square = -> $x { $x * 2 }; # this works with no return value
my #list = <1 2 3 4 5 6 7 8 9>.map( $square );
# returns [2 4 6 8 10 12 14 16 18]
I tried implementing fib() using an anonymous sub
my $fib = -> Int $x --> Int {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
$fib(13)
I get the following error when running that with explicit returns.
Attempt to return outside of any Routine
in block at test.p6 line 39
So I got rid of the return values.
my $fib = -> Int $x --> Int {
0 if $x == 0;
1 if $x == 1;
$fib($x - 1) + $fib($x - 2);
}
say $fib(13);
This last version never returns. Is there a way to write an anonymous recursive function without return values?
According to the documentation :
Blocks that aren't of type Routine (which is a subclass of Block) are
transparent to return.
sub f() {
say <a b c>.map: { return 42 };
# ^^^^^^ exits &f, not just the block }
The last statement is the implicit return value of the block
So you can try:
my $fib = -> Int $x --> Int {
if ( $x == 0 ) {
0; # <-- Implicit return value
}
elsif ( $x == 1 ) {
1; # <-- Implicit return value
}
else {
$fib($x - 1) + $fib($x - 2); # <-- Implicit return value
}
}
Three more options:
sub
You can write anonymous routines by using sub without a name:
my $fib = sub (Int $x --> Int) {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
say $fib(13); # 233
See #HåkonHægland's answer for why this (deliberately) doesn't work with non-routine blocks.
leave
The design anticipated your question:
my $fib = -> Int $x --> Int {
leave 0 if $x == 0;
leave 1 if $x == 1;
leave $fib($x - 1) + $fib($x - 2);
}
compiles. Hopefully you can guess that what it does -- or rather is supposed to do -- is exactly what you wanted to do.
Unfortunately, if you follow the above with:
say $fib(13);
You get a run-time error "leave not yet implemented".
My guess is that this'll get implemented some time in the next few years and the "Attempt to return outside of any Routine" error message will then mention leave. But implementing it has very low priority because it's easy to write sub as above, or write code as #HåkonHægland did, or use a case/switch statement construct as follows, and that's plenty good enough for now.
case/switch (when/default)
You can specify the parameter as $_ instead of $x and then you're all set to use constructs that refer to the topic:
my $fib = -> Int $_ --> Int {
when 0 { 0 }
when 1 { 1 }
$fib($_ - 1) + $fib($_ - 2)
}
say $fib(13); # 233
See when.
Blocks don't need to declare the return type. You can still return whatever you want, though. The problem is not in using return, it's in the declaration of the Int.
use v6;
my $fib = -> Int $x {
if $x == 0 {
0;
} elsif $x == 1 {
1;
} else {
$fib($x - 1) + $fib($x - 2);
}
}
say $fib(13) ;
The problem is that the return value needs to be the last executed. In the way you have done it, if it finds 0 or 1 it keeps running, getting to the last statement, when it will start all over again.
Alternatively, you can use given instead of the cascaded ifs. As long as whatever it returns is the last issued, it's OK.