问:
MPI Segmentation Fault On Multiple Nodes Only
So I am currently building the basis of a control program to run on multiple raspberry Pis that will use all of the available cores on each pi. When I test my code on one of the nodes using all of the cores it works fine, but using multiple nodes gives me a segmentation fault.

I looked at all the similar questions asked in the past, but they all had issues that would have broken my code on only one node too.

The full code:

```<code>#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <time.h>
int main(int argc, char *argv[])
{
        FILE *input;
        char batLine[86];   //may need to be made larger if bat commands get longer
        char sentbatch[86];
        int currentTask;
        int numTasks, rank, rc, i;
        MPI_Status stat;
        bool exitFlag = false;

        //mpi stuff
        MPI_Init(&argc,&argv);  //initilize mpi enviroment
        MPI_Comm_size(MPI_COMM_WORLD, &numTasks);
        MPI_Comm_rank(MPI_COMM_WORLD,&rank);
        //printf("Number of tasks: %d \n", numTasks);
        //printf ("MPI task %d has started...\n", rank);
        if(argc != 2)
        {
            printf("Usage: batallocation *.bat");
            exit(1); //exit with 1 indicates a failure
        }
        //contains file name: argv[1]
        input = fopen(argv[1],"r");

        currentTask = 0;
        if (rank ==0)
        {
            while(1)
            {
                if(exitFlag)
                    break; //allows to break out of while and for when no more lines exist
                char command[89] = "./";
                for(i=0; i < 16; i++) //will need to be 16 for full testing
                {

                    //fgets needs to be character count of longest line + 2 or it fails
                    if(fgets(batLine,86,input) != NULL)
                    {
                        printf("preview:%s\n",batLine);
                        if(i==0)
                        {
                            strcat(command,batLine);
                            printf("rank0 gets: %s\n", command);
                            //system(command);
                        }
                        else
                        {
                            //MPI_Send(buffer,count,type,dest,tag,comm)
                            MPI_Send(batLine,85,MPI_CHAR,i,i,MPI_COMM_WORLD);
                            printf("sent rank%d: %s\n",i,batLine);
                        }
                    }
                    else
                    {
                        exitFlag = true; //flag to break out of while loop
                        break;
                    }

                }
                //need to recieve data from other nodes here
                //put the data together in proper order
                //and only after that can the next sets be sent out

            }
        }
        else
        {
            char command[89] = "./";
            //MPI_Recv(buffer,count,type,source,tag,comm,status)
            MPI_Recv(sentbatch,86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);
            //using rank as flag makes it so only the wanted rank gets sent the data
            strcat(command,sentbatch); //adds needed ./ before batch data
            printf("rank=%d recieved data:%s",rank,sentbatch);
            //system(command); //should run batch line
        }
        fclose(input);
        MPI_Finalize();
        return(0);
}
</code>```

The contents of the file being passed:

```<code>
LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f
</code>```

You will notice I am not yet doing a few things that will be done in the final version and they are in comments to make trouble shooting easier. Mostly because the LAMOST code is not fast, and I do not want to be waiting for it to complete.

The command prompt that works and the output for it:

```<code> $mpiexec -N 4 --host 10.0.0.3 -oversubscribe batTest2 shortpass2.bat
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
</code>```

Shortpass2 is just the same file but with only the first 4 lines. My code should theoretically work with all 16 lines but I will test it with a full file after fixing the current issue.

Running on multiple nodes command and output:

```<code>$mpiexec -N 4 --host 10.0.0.3,10.0.0.4,10.0.0.5,10.0.0.6 -oversubscribe batTest2 shortpass.bat

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
sent rank4: LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

rank=4 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
[node2:27622] *** Process received signal ***
[node2:27622] Signal: Segmentation fault (11)
[node2:27622] Signal code: Address not mapped (1)
[node2:27622] Failing at address: (nil)
[node2:27622] *** End of error message ***
--------------------------------------------------------------------------
Primary job  terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.
--------------------------------------------------------------------------
corrupted double-linked list
Aborted
</code>```

Sometimes it will successfully get to rank 5 before aborting completely, and there will be multiple instances of the same error message. Additionally, Open MPI was installed with multiple thread support so that isn't the issue. This is my first time using MPI but this is not the first part of the whole project and I have done a ton of research into MPI to even get this far with it.

I know it isn't caused by my arrays since then it would be breaking on node1 as well. All of the pis are identical so it wouldn't make sense for the arrays to be causing the segmentation faults. (Although I admit I have had that issue come up several times working on the different parts of this project because I am more used to how Java and C# handle arrays)

Edit: I checked to see if I could run it across 4 cores from one of the other nodes and that works fine and produces the same output as it did on node1. So that confirms it not being an array issue that only happens on the other nodes.
Also added a line that was missing in the code for the preview print out.

Edit2: Per Gilles suggestion: The code works with running 16 tasks all on one node as well. Here is the output from that:

```<code>$ mpiexec -N 16 --host 10.0.0.3 -oversubscribe batTest4 shortpass.bat
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

sent rank4: LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

sent rank5: LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f

sent rank6: LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f

sent rank7: LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f

sent rank8: LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f

sent rank9: LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f

sent rank10: LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f

sent rank11: LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f

sent rank12: LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f

sent rank13: LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f

sent rank14: LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f

sent rank15: LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f

rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
rank=5 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f
rank=6 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f
rank=7 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f
rank=11 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f
rank=12 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f
rank=9 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f
rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
rank=4 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
rank=8 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f
rank=10 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f
rank=15 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f
rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
rank=13 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f
rank=14 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f
</code>```

答:
Not sure if that is the problem, but it definitely is a problem:

You are reading and then sending 85 characters from batLine here:

```<code>char batLine[86];

//fgets needs to be character count of longest line + 2 or it fails
if(fgets(batLine,86,input) != NULL)
{
    // ...
    MPI_Send(batLine,85,MPI_CHAR,i,i,MPI_COMM_WORLD);
    // ...
}
</code>```

Given that batLine[] is 86 elements, and that LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f\n is 85 characters long, the string you are sending doesn't include the \0 terminator which is in the 86-th array element.

On the receiving side you have:

```<code>char sentbatch[86];

{
    char command[89] = "./";
    // ...
    MPI_Recv(sentbatch,86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);
    strcat(command,sentbatch);
    // ...
}
</code>```

sentbatch is never initialised, so initially it contains garbage. Since all incoming messages are 85 characters long, the 86-th character is never overwritten and it keeps holding whatever garbage was there initially. Consequently, if that wasn't \0, then strcat() will continue reading garbage from sentbatch past the 85-th character and appending to command. Since both command and sentbatch are on the stack, the read will continue either until it hits a 0x00 somewhere on the stack, at which point writing past the end of command will have destroyed other local variables or even the stack frame causing a potential segfault later on, or until it reaches the end of the stack, which will definitely cause a segfault. That it works sometimes and in some ranks is purely by accident.

Either change MPI_Send to send 86 characters or explicitly zero the 86-th element of sentbatch. Or, even better, use strncat(command, sentbatch, 85) to append no more than 85 characters or directly receive into command using

```<code>MPI_Recv(&command[2],86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);
</code>```

char command[89] = "./"; pads the remaining 87 elements of command[] with \0, so no problems with the terminator in this case.

Body:
So I am currently building the basis of a control program to run on multiple raspberry Pis that will use all of the available cores on each pi. When I test my code on one of the nodes using all of the cores it works fine, but using multiple nodes gives me a segmentation fault.

I looked at all the similar questions asked in the past, but they all had issues that would have broken my code on only one node too.

The full code:

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <time.h>
int main(int argc, char *argv[])
{
        FILE *input;
        char batLine[86];   //may need to be made larger if bat commands get longer
        char sentbatch[86];
        int currentTask;
        int numTasks, rank, rc, i;
        MPI_Status stat;
        bool exitFlag = false;

        //mpi stuff
        MPI_Init(&argc,&argv);  //initilize mpi enviroment
        MPI_Comm_size(MPI_COMM_WORLD, &numTasks);
        MPI_Comm_rank(MPI_COMM_WORLD,&rank);
        //printf("Number of tasks: %d \n", numTasks);
        //printf ("MPI task %d has started...\n", rank);
        if(argc != 2)
        {
            printf("Usage: batallocation *.bat");
            exit(1); //exit with 1 indicates a failure
        }
        //contains file name: argv[1]
        input = fopen(argv[1],"r");

        currentTask = 0;
        if (rank ==0)
        {
            while(1)
            {
                if(exitFlag)
                    break; //allows to break out of while and for when no more lines exist
                char command[89] = "./";
                for(i=0; i < 16; i++) //will need to be 16 for full testing
                {

                    //fgets needs to be character count of longest line + 2 or it fails
                    if(fgets(batLine,86,input) != NULL)
                    {
                        printf("preview:%s\n",batLine);
                        if(i==0)
                        {
                            strcat(command,batLine);
                            printf("rank0 gets: %s\n", command);
                            //system(command);
                        }
                        else
                        {
                            //MPI_Send(buffer,count,type,dest,tag,comm)
                            MPI_Send(batLine,85,MPI_CHAR,i,i,MPI_COMM_WORLD);
                            printf("sent rank%d: %s\n",i,batLine);
                        }
                    }
                    else
                    {
                        exitFlag = true; //flag to break out of while loop
                        break;
                    }

                }
                //need to recieve data from other nodes here
                //put the data together in proper order
                //and only after that can the next sets be sent out

            }
        }
        else
        {
            char command[89] = "./";
            //MPI_Recv(buffer,count,type,source,tag,comm,status)
            MPI_Recv(sentbatch,86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);
            //using rank as flag makes it so only the wanted rank gets sent the data
            strcat(command,sentbatch); //adds needed ./ before batch data
            printf("rank=%d recieved data:%s",rank,sentbatch);
            //system(command); //should run batch line
        }
        fclose(input);
        MPI_Finalize();
        return(0);
}

The contents of the file being passed:

LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f
LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f

You will notice I am not yet doing a few things that will be done in the final version and they are in comments to make trouble shooting easier. Mostly because the LAMOST code is not fast, and I do not want to be waiting for it to complete.

The command prompt that works and the output for it:

 $mpiexec -N 4 --host 10.0.0.3 -oversubscribe batTest2 shortpass2.bat
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

Shortpass2 is just the same file but with only the first 4 lines. My code should theoretically work with all 16 lines but I will test it with a full file after fixing the current issue.

Running on multiple nodes command and output:

$mpiexec -N 4 --host 10.0.0.3,10.0.0.4,10.0.0.5,10.0.0.6 -oversubscribe batTest2 shortpass.bat

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
sent rank4: LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

rank=4 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
[node2:27622] *** Process received signal ***
[node2:27622] Signal: Segmentation fault (11)
[node2:27622] Signal code: Address not mapped (1)
[node2:27622] Failing at address: (nil)
[node2:27622] *** End of error message ***
--------------------------------------------------------------------------
Primary job  terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.
--------------------------------------------------------------------------
corrupted double-linked list
Aborted

Sometimes it will successfully get to rank 5 before aborting completely, and there will be multiple instances of the same error message. Additionally, Open MPI was installed with multiple thread support so that isn't the issue. This is my first time using MPI but this is not the first part of the whole project and I have done a ton of research into MPI to even get this far with it.

I know it isn't caused by my arrays since then it would be breaking on node1 as well. All of the pis are identical so it wouldn't make sense for the arrays to be causing the segmentation faults. (Although I admit I have had that issue come up several times working on the different parts of this project because I am more used to how Java and C# handle arrays)

Edit: I checked to see if I could run it across 4 cores from one of the other nodes and that works fine and produces the same output as it did on node1. So that confirms it not being an array issue that only happens on the other nodes.
Also added a line that was missing in the code for the preview print out.

Edit2: Per Gilles suggestion: The code works with running 16 tasks all on one node as well. Here is the output from that:

$ mpiexec -N 16 --host 10.0.0.3 -oversubscribe batTest4 shortpass.bat
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

rank0 gets: ./LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

sent rank1: LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f

sent rank2: LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

sent rank3: LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

sent rank4: LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

sent rank5: LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f

sent rank6: LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f

sent rank7: LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f

sent rank8: LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f

sent rank9: LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f

sent rank10: LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f

sent rank11: LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f

sent rank12: LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f

sent rank13: LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f

sent rank14: LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f

preview:LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f

sent rank15: LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f

rank=3 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-005.flx spec-56321-GAC099N59V1_sp01-005.nor f
rank=5 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-008.flx spec-56321-GAC099N59V1_sp01-008.nor f
rank=6 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-010.flx spec-56321-GAC099N59V1_sp01-010.nor f
rank=7 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-013.flx spec-56321-GAC099N59V1_sp01-013.nor f
rank=11 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-023.flx spec-56321-GAC099N59V1_sp01-023.nor f
rank=12 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-024.flx spec-56321-GAC099N59V1_sp01-024.nor f
rank=9 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-018.flx spec-56321-GAC099N59V1_sp01-018.nor f
rank=2 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-004.flx spec-56321-GAC099N59V1_sp01-004.nor f
rank=4 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-006.flx spec-56321-GAC099N59V1_sp01-006.nor f
rank=8 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-015.flx spec-56321-GAC099N59V1_sp01-015.nor f
rank=10 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-022.flx spec-56321-GAC099N59V1_sp01-022.nor f
rank=15 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-029.flx spec-56321-GAC099N59V1_sp01-029.nor f
rank=1 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-003.flx spec-56321-GAC099N59V1_sp01-003.nor f
rank=13 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-025.flx spec-56321-GAC099N59V1_sp01-025.nor f
rank=14 recieved data:LAMOSTv108 spec-56321-GAC099N59V1_sp01-028.flx spec-56321-GAC099N59V1_sp01-028.nor f

Body:
Not sure if that is the problem, but it definitely is a problem:

You are reading and then sending 85 characters from batLine here:

char batLine[86];

//fgets needs to be character count of longest line + 2 or it fails
if(fgets(batLine,86,input) != NULL)
{
    // ...
    MPI_Send(batLine,85,MPI_CHAR,i,i,MPI_COMM_WORLD);
    // ...
}

Given that batLine[] is 86 elements, and that LAMOSTv108 spec-56321-GAC099N59V1_sp01-001.flx spec-56321-GAC099N59V1_sp01-001.nor f\n is 85 characters long, the string you are sending doesn't include the \0 terminator which is in the 86-th array element.

On the receiving side you have:

char sentbatch[86];

{
    char command[89] = "./";
    // ...
    MPI_Recv(sentbatch,86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);
    strcat(command,sentbatch);
    // ...
}

sentbatch is never initialised, so initially it contains garbage. Since all incoming messages are 85 characters long, the 86-th character is never overwritten and it keeps holding whatever garbage was there initially. Consequently, if that wasn't \0, then strcat() will continue reading garbage from sentbatch past the 85-th character and appending to command. Since both command and sentbatch are on the stack, the read will continue either until it hits a 0x00 somewhere on the stack, at which point writing past the end of command will have destroyed other local variables or even the stack frame causing a potential segfault later on, or until it reaches the end of the stack, which will definitely cause a segfault. That it works sometimes and in some ranks is purely by accident.

Either change MPI_Send to send 86 characters or explicitly zero the 86-th element of sentbatch. Or, even better, use strncat(command, sentbatch, 85) to append no more than 85 characters or directly receive into command using

MPI_Recv(&command[2],86,MPI_CHAR,0,rank,MPI_COMM_WORLD,&stat);

char command[89] = "./"; pads the remaining 87 elements of command[] with \0, so no problems with the terminator in this case.


来源: stackexchange

问:
Swift Core Data - storing an array of custom types
I am trying to create a data model which mirrors a view model that I use to handle an API call, the idea being that I will be able to store all the necessary data in core data and then access it when the user is offline, effectively giving the app offline functionality.

However, there is one entity which I need to store which is an array of a custom class that I have in the app:

```<code>[OrderSheet]
</code>```

This is a struct defined as follows:

```<code>struct OrderSheet {
    let order: SheetClass // codable class
    let sheet: Sheet // codable struct

    init(fuelOrder: SheetClass, sheet: Sheet) {
    self.order = order
    self.sheet = sheet
    }
}
</code>```

How can I create an entity that would be capable of storing the above?

答:
One simple way would be to have an entity that holds only one Data field (Binary Data in xcdatamodel settings), which would be the orderSheet itself.

Before going with this solution, I'd like to mention that, one down side of this approach is; if later in the future, any of the models inside OrderSheet changes, you won't be able to retrieve already stored objects as conversion will fail. One way of overcoming this issue would be declaring everything inside OrderSheet and sub models as Optional. But if it is not so crucial, meaning, if not being able to read old models on user's device after an app update is okay, (maybe they will be replaced with new networking call) then you can go with not marking properties as optional either.

Lets imagine you create an entity named OrderSheetManaged with one field as I mentioned like following:

```<code>import Foundation
import CoreData

@objc(Entity)
public class OrderSheetManaged: NSManagedObject {

}

extension OrderSheetManaged {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<OrderSheetManaged> {
        return NSFetchRequest<OrderSheetManaged>(entityName: "OrderSheetManaged")
    }
    @NSManaged public var orderSheet: Data?
}
</code>```

I will write some code for NSManagedObjectContext, which is not directly related to your question, you should make research on how to initialise a core data stack and a managed context from it if you are not familiar with that since it is crucial.

I also do some force unwrapping for simplicity, make sure to not force unwrap where not needed in production code.

Now whenever you have an actual OrderSheet object (it is orderSheet in my example below), that was parsed before, you are going to convert it to Data and persist it with new Core Data model as following:

```<code>// unrelated to question, it should already be initialised from core data stack, I just init with
// concurrency type to make compiler happy, dont do this before further research.
let yourManagedContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
let entityDescription = NSEntityDescription.entity(forEntityName: "OrderSheetManaged",
                                                   in: yourManagedContext)

let dataForCoreData = try! JSONEncoder().encode(orderSheet)

let managedOrderSheet = NSManagedObject(entity: entityDescription!, insertInto: yourManagedContext)
managedOrderSheet.setValue(dataForCoreData, forKey: "orderSheet")
</code>```

Now we have persisted your object as Data inside a wrapper core data model (OrderSheetManaged)

Let's see now how we can fetch these models from our core data and convert it back to OrderSheet model:

```<code>// when you fetch it
var orderSheets = [OrderSheet]()
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "OrderSheetManaged")
var coreDataObjects: [NSManagedObject]!
do {
    coreDataObjects = try yourManagedContext.fetch(request) as? [NSManagedObject]

    for coreDataObject in coreDataObjects {
        if let orderSheetData = coreDataObject.value(forKey: "orderSheet") as? Data {
            let orderSheet = try! JSONDecoder().decode(OrderSheet.self, from: orderSheetData)
            orderSheets.append(orderSheet)
        }
    }
} catch {
    error
}
</code>```

Now you will have all your stored order sheets inside orderSheets array.

You can also write some utility methods to easily modify core data models by converting orderSheet data inside of them to OrderSheet first and then again converting it back to Data after modifying and then persisting again with setValue.

ContentLicense: CC BY-SA 4.0

Body:
I am trying to create a data model which mirrors a view model that I use to handle an API call, the idea being that I will be able to store all the necessary data in core data and then access it when the user is offline, effectively giving the app offline functionality.

However, there is one entity which I need to store which is an array of a custom class that I have in the app:

[OrderSheet]

This is a struct defined as follows:

struct OrderSheet {
    let order: SheetClass // codable class
    let sheet: Sheet // codable struct

    init(fuelOrder: SheetClass, sheet: Sheet) {
    self.order = order
    self.sheet = sheet
    }
}

How can I create an entity that would be capable of storing the above?

Body:
One simple way would be to have an entity that holds only one Data field (Binary Data in xcdatamodel settings), which would be the orderSheet itself.

Before going with this solution, I'd like to mention that, one down side of this approach is; if later in the future, any of the models inside OrderSheet changes, you won't be able to retrieve already stored objects as conversion will fail. One way of overcoming this issue would be declaring everything inside OrderSheet and sub models as Optional. But if it is not so crucial, meaning, if not being able to read old models on user's device after an app update is okay, (maybe they will be replaced with new networking call) then you can go with not marking properties as optional either.

Lets imagine you create an entity named OrderSheetManaged with one field as I mentioned like following:

import Foundation
import CoreData

@objc(Entity)
public class OrderSheetManaged: NSManagedObject {

}

extension OrderSheetManaged {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<OrderSheetManaged> {
        return NSFetchRequest<OrderSheetManaged>(entityName: "OrderSheetManaged")
    }
    @NSManaged public var orderSheet: Data?
}

I will write some code for NSManagedObjectContext, which is not directly related to your question, you should make research on how to initialise a core data stack and a managed context from it if you are not familiar with that since it is crucial.

I also do some force unwrapping for simplicity, make sure to not force unwrap where not needed in production code.

Now whenever you have an actual OrderSheet object (it is orderSheet in my example below), that was parsed before, you are going to convert it to Data and persist it with new Core Data model as following:

// unrelated to question, it should already be initialised from core data stack, I just init with
// concurrency type to make compiler happy, dont do this before further research.
let yourManagedContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
let entityDescription = NSEntityDescription.entity(forEntityName: "OrderSheetManaged",
                                                   in: yourManagedContext)

let dataForCoreData = try! JSONEncoder().encode(orderSheet)

let managedOrderSheet = NSManagedObject(entity: entityDescription!, insertInto: yourManagedContext)
managedOrderSheet.setValue(dataForCoreData, forKey: "orderSheet")

Now we have persisted your object as Data inside a wrapper core data model (OrderSheetManaged)

Let's see now how we can fetch these models from our core data and convert it back to OrderSheet model:

// when you fetch it
var orderSheets = [OrderSheet]()
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "OrderSheetManaged")
var coreDataObjects: [NSManagedObject]!
do {
    coreDataObjects = try yourManagedContext.fetch(request) as? [NSManagedObject]

    for coreDataObject in coreDataObjects {
        if let orderSheetData = coreDataObject.value(forKey: "orderSheet") as? Data {
            let orderSheet = try! JSONDecoder().decode(OrderSheet.self, from: orderSheetData)
            orderSheets.append(orderSheet)
        }
    }
} catch {
    error
}

Now you will have all your stored order sheets inside orderSheets array.

You can also write some utility methods to easily modify core data models by converting orderSheet data inside of them to OrderSheet first and then again converting it back to Data after modifying and then persisting again with setValue.


问:
Least common ancestor of multiple nodes in DAG
How can I find a least common ancestors of multiple nodes in a directed acyclic graph?

I've found quite a few papers on the topic but they all seem to find LCAs in DAG for two nodes.

Are there good algorithms for multiple nodes?

答:
As @DennisMeng, @vzn and @user824425 already pointed out in the comments, under certain circumstances (!) the LCA of more than two nodes can be computed by pairwise recursive application of the (binary) LCA operator, e.g.:

```<code>lca(A, B, C, D) = lca(A, lca(B, lca(C, D)))
</code>```

In functional programming, this is basically equivalent to a reduce (or fold) operation.

However, this is only true for DAGs that are Multitrees (or, alternatively, diamond-free posets). For general DAGs that don't have the multitree/diamond-free poset property, this approach will unfortunately not work.

Consider the following DAG representing a class hierarchy that features multiple inheritance (all edges are directed from the bottom to the top; the X indicates a crossing of two directed edges):

```<code>        Any
       /   \
  Boolean Value
      |  X  |  \
    False True Unknown
</code>```

Notably, the True and False nodes both have two direct ancestors, Boolean and Value. The first problem here is that this requires an LCA operator that can return more than one node, such as JGraphT's getLCASet. Now, let's say we wanted to compute the LCA of {False, True, Unknown}: by simply looking at the graph, it is pretty obvious that Value is a direct ancestor of all three nodes. Direct pairwise reduction is no longer applicable, because the binary getLCASet operator can return more than one node, but conceivably one could use a stack-like approach where the computed ancestors get pushed back to the list of nodes. However, this does not produce the correct result, e.g.:

```<code>  True, False, Unknown
     \   /
     (LCA)
     /   \
Boolean, Value, Unknown
     \   /
     (LCA)
       |
      Any, Unknown
        \   /
        (LCA)
          |
         Any
</code>```

ContentLicense: CC BY-SA 3.0

Body:
As @DennisMeng, @vzn and @user824425 already pointed out in the comments, under certain circumstances (!) the LCA of more than two nodes can be computed by pairwise recursive application of the (binary) LCA operator, e.g.:

lca(A, B, C, D) = lca(A, lca(B, lca(C, D)))

In functional programming, this is basically equivalent to a reduce (or fold) operation.

However, this is only true for DAGs that are Multitrees (or, alternatively, diamond-free posets). For general DAGs that don't have the multitree/diamond-free poset property, this approach will unfortunately not work.

Consider the following DAG representing a class hierarchy that features multiple inheritance (all edges are directed from the bottom to the top; the X indicates a crossing of two directed edges):

        Any
       /   \
  Boolean Value
      |  X  |  \
    False True Unknown

Notably, the True and False nodes both have two direct ancestors, Boolean and Value. The first problem here is that this requires an LCA operator that can return more than one node, such as JGraphT's getLCASet. Now, let's say we wanted to compute the LCA of {False, True, Unknown}: by simply looking at the graph, it is pretty obvious that Value is a direct ancestor of all three nodes. Direct pairwise reduction is no longer applicable, because the binary getLCASet operator can return more than one node, but conceivably one could use a stack-like approach where the computed ancestors get pushed back to the list of nodes. However, this does not produce the correct result, e.g.:

  True, False, Unknown
     \   /
     (LCA)
     /   \
Boolean, Value, Unknown
     \   /
     (LCA)
       |
      Any, Unknown
        \   /
        (LCA)
          |
         Any


问:
Launch bash subshell and run commands in a script
I want to write a shell script that does the following:

Activate pipenv virtual environment

Runs mkdocs serve which starts a local dev server for my mkdocs documentation

If I do the naïve thing and put this in my script:

```<code>cd <my-docs-directory>
pipenv shell
mkdocs serve
</code>```

it fails because pipenv shell "launches a subshell in the virtual environment". I need to pass the mkdocs serve command into the virtual shell (and preferably land in that same shell after running the script ).

Thanks in advance!

Answer

Philippe's answer works. Here's why.

```<code>pipenv run bash -c 'mkdocs serve ; exec bash --norc'
</code>```

Pipenv allows you to run a command in the virtual environment without launching a shell:

```<code>$ pipenv run <insert command here>
</code>```

bash -c <insert command here> allows you to pass a command to bash to execute

```<code>$ bash -c "echo hello"
hello
</code>```

exec serves to replace current shell process with a command, so that parent goes a way and child owns pid. Here's a related question on AskUbuntu.

答:
You can use this command :</p>

```<code>pipenv run bash -c 'mkdocs serve ; exec bash --norc'
</code>```

Body:
I want to write a shell script that does the following:

Activate pipenv virtual environment

Runs mkdocs serve which starts a local dev server for my mkdocs documentation

If I do the naïve thing and put this in my script:

cd <my-docs-directory>
pipenv shell
mkdocs serve

it fails because pipenv shell "launches a subshell in the virtual environment". I need to pass the mkdocs serve command into the virtual shell (and preferably land in that same shell after running the script ).

Thanks in advance!

Answer

Philippe's answer works. Here's why.

pipenv run bash -c 'mkdocs serve ; exec bash --norc'

Pipenv allows you to run a command in the virtual environment without launching a shell:

$ pipenv run <insert command here>

bash -c <insert command here> allows you to pass a command to bash to execute

$ bash -c "echo hello"
hello

exec serves to replace current shell process with a command, so that parent goes a way and child owns pid. Here's a related question on AskUbuntu.

Body:
You can use this command :

pipenv run bash -c 'mkdocs serve ; exec bash --norc'


问:
How to remove action bar in react native
Hi I am developing an android app with react native. i am trying to remove the action bar(Home) from HomeScreen.js my code is

```<code>import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';

class HomeScreen extends Component {
   render() {
      return (
          <View style={styles.container}>
            <Text>HomeScreen</Text>
          </View>
        );
   }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#2c3e50',
     },
});

export default HomeScreen;
</code>```

enter image description here

答:
If you are using React Navigation, The Stack Navigator has a header by default, you need to give the value of null to the header prop for navigationOptions. </p>

<p>You can add this function in your HomeScreen class.  </p>

```<code>static navigationOptions = {
    header: null,
    };
</code>```

Body:
Hi I am developing an android app with react native. i am trying to remove the action bar(Home) from HomeScreen.js my code is

import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';

class HomeScreen extends Component {
   render() {
      return (
          <View style={styles.container}>
            <Text>HomeScreen</Text>
          </View>
        );
   }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#2c3e50',
     },
});

export default HomeScreen;

enter image description here

Body:
If you are using React Navigation, The Stack Navigator has a header by default, you need to give the value of null to the header prop for navigationOptions.

You can add this function in your HomeScreen class.

static navigationOptions = {
    header: null,
    };


问:
Need help scaling an image inside a viewport
I have a Django site that displays an image and I need to zoom in and zoom out using a button while keeping the viewport relatively the same size and use scroll bars to move the image when it is zoomed in. I am not a CSS nor javascript guy, so this attempt is based on a lot of google help.

$(document).ready(function() {
  console.log("Zoom START");
  $('#zoom-in').click(function() {
    updateZoom(0.1);
    console.log("Zoomed in");
  });

  $('#zoom-out').click(function() {
    updateZoom(-0.1);
    console.log("Zoomed out");
  });

  zoomLevel = 1;

  var updateZoom = function(zoom) {
    zoomLevel += zoom;
    $('#imageblock').css({
      zoom: zoomLevel,
      '-moz-transform': 'scale(' + zoomLevel + ')',
      /* Firefox */
      'transform': 'scale(' + zoomLevel + ')',
      //'-ms-transform': 'scale(' + zoomLevel + ')', /* IE 9 */
      '-webkit-transform': 'scale(' + zoomLevel + ')',
      /* Safari and Chrome */
      //'-o-transform': 'scale(' + zoomLevel + ')', /* Opera */

    });
    console.log("updated imageblock css");
  }
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>#imageblock {
  max-height: 600px;
  max-width: 800px;
  transform-origin: top left;
  overflow: hidden;
}

#imageblock img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}</code>```

Image:

    Click to tag people, Ctrl-click to tag animals
    <button type="button" id="zoom-in">zoom in</button> <button type="button" id="zoom-out">zoom out</button>

    Rotate 90 degrees

```

The image zooms, but also grows to fill the page without any scrollbars, and does not stay within a viewport (image block). Thanks for any assistance/direction you can give me!

Mark

答:
try to give the parent div overflow: hidden</p>

```<code>readonly{
overflow: hidden
}
</code>```

Body:
I have a Django site that displays an image and I need to zoom in and zoom out using a button while keeping the viewport relatively the same size and use scroll bars to move the image when it is zoomed in. I am not a CSS nor javascript guy, so this attempt is based on a lot of google help.

$(document).ready(function() {
  console.log("Zoom START");
  $('#zoom-in').click(function() {
    updateZoom(0.1);
    console.log("Zoomed in");
  });

  $('#zoom-out').click(function() {
    updateZoom(-0.1);
    console.log("Zoomed out");
  });

  zoomLevel = 1;

  var updateZoom = function(zoom) {
    zoomLevel += zoom;
    $('#imageblock').css({
      zoom: zoomLevel,
      '-moz-transform': 'scale(' + zoomLevel + ')',
      /* Firefox */
      'transform': 'scale(' + zoomLevel + ')',
      //'-ms-transform': 'scale(' + zoomLevel + ')', /* IE 9 */
      '-webkit-transform': 'scale(' + zoomLevel + ')',
      /* Safari and Chrome */
      //'-o-transform': 'scale(' + zoomLevel + ')', /* Opera */

    });
    console.log("updated imageblock css");
  }
});

#imageblock {
  max-height: 600px;
  max-width: 800px;
  transform-origin: top left;
  overflow: hidden;
}

#imageblock img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

Image:

    Click to tag people, Ctrl-click to tag animals
    <button type="button" id="zoom-in">zoom in</button> <button type="button" id="zoom-out">zoom out</button>

    Rotate 90 degrees

The image zooms, but also grows to fill the page without any scrollbars, and does not stay within a viewport (image block). Thanks for any assistance/direction you can give me!

Mark

Body:
try to give the parent div overflow: hidden

readonly{
overflow: hidden
}


问:
Group by all columns in a data.table
I'm working with iris data.table in R.

To remind how it looks I paste six five rows here

```<code>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1:          5.1         3.5          1.4         0.2  setosa
2:          4.9         3.0          1.4         0.2  setosa
3:          4.7         3.2          1.3         0.2  setosa
4:          4.6         3.1          1.5         0.2  setosa
5:          5.0         3.6          1.4         0.2  setosa
6:          5.4         3.9          1.7         0.4  setosa
</code>```

I would like to calculate the number of rows, grouped by all columns. Of course we may write all variables in by, like this:

```<code>iris[, .(Freq = .N), by = .(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Freq
1:          5.1         3.5          1.4         0.2  setosa    1
2:          4.9         3.0          1.4         0.2  setosa    1
3:          4.7         3.2          1.3         0.2  setosa    1
4:          4.6         3.1          1.5         0.2  setosa    1
5:          5.0         3.6          1.4         0.2  setosa    1
6:          5.4         3.9          1.7         0.4  setosa    1
</code>```

However, I wonder if there is a method to group by all variables without needing to type all the columns names?

答:
In case you are looking for duplicates, uniqueN will default to using all columns:

```<code>uniqueN(as.data.table(iris))
# [1] 149
</code>```

This doesn't answer your question directly, but it might be a more direct way of accomplishing what you were trying to do in the first place.

Similarly, if you're looking for which rows are duplicated, you can use duplicated's data.table method which similarly defaults to using all columns:

```<code>iris[duplicated(iris)]
#    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
# 1:          5.8         2.7          5.1         1.9 virginica
</code>```

Title: Group by all columns in a data.table

Body:
I'm working with iris data.table in R.

To remind how it looks I paste six five rows here

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1:          5.1         3.5          1.4         0.2  setosa
2:          4.9         3.0          1.4         0.2  setosa
3:          4.7         3.2          1.3         0.2  setosa
4:          4.6         3.1          1.5         0.2  setosa
5:          5.0         3.6          1.4         0.2  setosa
6:          5.4         3.9          1.7         0.4  setosa

I would like to calculate the number of rows, grouped by all columns. Of course we may write all variables in by, like this:

iris[, .(Freq = .N), by = .(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Freq
1:          5.1         3.5          1.4         0.2  setosa    1
2:          4.9         3.0          1.4         0.2  setosa    1
3:          4.7         3.2          1.3         0.2  setosa    1
4:          4.6         3.1          1.5         0.2  setosa    1
5:          5.0         3.6          1.4         0.2  setosa    1
6:          5.4         3.9          1.7         0.4  setosa    1

However, I wonder if there is a method to group by all variables without needing to type all the columns names?

Body:
In case you are looking for duplicates, uniqueN will default to using all columns:

uniqueN(as.data.table(iris))
# [1] 149

This doesn't answer your question directly, but it might be a more direct way of accomplishing what you were trying to do in the first place.

Similarly, if you're looking for which rows are duplicated, you can use duplicated's data.table method which similarly defaults to using all columns:

iris[duplicated(iris)]
#    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
# 1:          5.8         2.7          5.1         1.9 virginica


问:
how to break a while loop immediately
I have this Class ScaleWorker

which is a worker running in a thread in the main interface

it contains receave_scaledata which waits for receaving data from a device and forward it to the
interface

the function runs in a while loop
with the condition while my_serial.is_open and self.continue_run:

with the function

```<code>def stop_me(self):
        self.continue_run = False

</code>```

the function can be stopped when a signal is send from the main interface to execute stop_me

self.continue_run = True is switched to True and the loop breaks

at the end it emits self.finishedworking.emit()
which tell the thread in the main interface to quit

self.scaleworker.finishedworking.connect(self.thread.quit)

The Problem is that the function receave_scaledata contains a function from pyserial

data_left = my_serial.inWaiting()

this function waits forever till it receaves data

 without incoming data the other code gets not executed
so when a signal is send to quit the thread the signal is stuck till data comes into the device and then the loop breaks

Im looking for a way to tell the worker to emit finishedworking right away without getting blocked
So far I could not find a way around it

the code is a little bit hard to execute withpout the device but maybe you can help me

here is the Code

```<code>import sys
import time

import re
import serial
from serial.tools import list_ports

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc

class ScaleWorker(qtc.QObject):

    work_signal = qtc.pyqtSignal(float)
    finishedworking = qtc.pyqtSignal()  # emmits that its finished

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.continue_run = False

    @qtc.pyqtSlot()
    def receave_scaledata(self):
        try:
            my_serial = serial.Serial(
                port="COM 3",
                baudrate=2400,
                bytesize=7,
                parity=serial.PARITY_NONE,
                timeout=None,
                stopbits=1,)

            if my_serial.is_open:
                print("serial open")

                while my_serial.is_open and self.continue_run:
                    data = my_serial.read()  # wait forever till data arives
                    time.sleep(1)  # hard delay to receave all bites
                    data_left = my_serial.inWaiting()  # wait forever
                    data += my_serial.read(data_left) # pack all receaved bites into on variable
                    self.work_signal.emit(data)
                self.finishedworking.emit()

        except serial.serialutil.SerialException:
            print("not open")

    def stop_me(self):
        self.continue_run = False

</code>```

答:
I simple yet robust way is to configure a rather short read timeout (~1 second) on the Serial port. You will just have to test whether len(data) == 0 and do not process further the (non) incoming data.

That way you can be sure to be able to test for the stop request at least on each occurence of the timeout.

Title: how to break a while loop immediately

Body:
I have this Class ScaleWorker

which is a worker running in a thread in the main interface

it contains receave_scaledata which waits for receaving data from a device and forward it to the
interface

the function runs in a while loop
with the condition while my_serial.is_open and self.continue_run:

with the function

def stop_me(self):
        self.continue_run = False

the function can be stopped when a signal is send from the main interface to execute stop_me

self.continue_run = True is switched to True and the loop breaks

at the end it emits self.finishedworking.emit()
which tell the thread in the main interface to quit

self.scaleworker.finishedworking.connect(self.thread.quit)

The Problem is that the function receave_scaledata contains a function from pyserial

data_left = my_serial.inWaiting()

this function waits forever till it receaves data

 without incoming data the other code gets not executed
so when a signal is send to quit the thread the signal is stuck till data comes into the device and then the loop breaks

Im looking for a way to tell the worker to emit finishedworking right away without getting blocked
So far I could not find a way around it

the code is a little bit hard to execute withpout the device but maybe you can help me

here is the Code

import sys
import time

import re
import serial
from serial.tools import list_ports

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc

class ScaleWorker(qtc.QObject):

    work_signal = qtc.pyqtSignal(float)
    finishedworking = qtc.pyqtSignal()  # emmits that its finished

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.continue_run = False

    @qtc.pyqtSlot()
    def receave_scaledata(self):
        try:
            my_serial = serial.Serial(
                port="COM 3",
                baudrate=2400,
                bytesize=7,
                parity=serial.PARITY_NONE,
                timeout=None,
                stopbits=1,)

            if my_serial.is_open:
                print("serial open")

                while my_serial.is_open and self.continue_run:
                    data = my_serial.read()  # wait forever till data arives
                    time.sleep(1)  # hard delay to receave all bites
                    data_left = my_serial.inWaiting()  # wait forever
                    data += my_serial.read(data_left) # pack all receaved bites into on variable
                    self.work_signal.emit(data)
                self.finishedworking.emit()

        except serial.serialutil.SerialException:
            print("not open")

    def stop_me(self):
        self.continue_run = False


问:
Unable to separate csv's into separate columns
I have used the following function to create a unique data_frame with csv's (already encoded in UTF-8 form):

```<code>library(readr)
comentarios_hoteles<-list.files(path="C:/Users/OneDrive/Documentos/DFBA/ Melia", pattern="*.csv", full.names=TRUE) %>%
  lapply(read_csv)%>%
  bind_rows
</code>```

For some reason I am getting all the observations in one column instead of in 6.

```<code>This is the full code:
Comentario,"Fecha","Mes","Estación","Hotel","Marca"
1   No todas las instalaciones del hotel se pudieron usar, estaban cerradas sin avisar previamente al cliente. Se intentó hacer un cambio en las fechas de la reserva debido al temporal de calima que hubo (no porque no quisiéramos irnos de hotel) y no dejaron (añadiendo que el tiempo estaba mucho mejor que el día anterior) y tampoco propusieron solución. Al llegar al hotel, vemos que la piscina está cerrada por dicho temporal, por lo que encima no se podía disfrutar de todas las instalaciones. Los desayunos muy bien, variados. No puedo decir lo mismo de las cenas: arroz pasado y con olor, poca variedad y para colmo los camareros sirviéndose la cena sin darte paso a ti, cliente, a servite no siendo que le quitaramos el trozo de pizza que quería... En fin... Yo siempre que voy a hotel, voy a los Melia, pero este en concreto no está a la altura de lo que acostumbra la marca, por lo que no lo recomendaría. …,2020-02-01,"feb.","Invierno","Sol Arona Tenerife","Sol"
2   Me he ido con un buen sabor de boca, y ganas de volver. Me ha sorprendido totalmente el hotel.  Nuestra habitación en la planta 14, era genial! Espaciosa, bien cuidada, vistas preciosas, limpieza bien.  Servicio de restaurante con horario amplio. El día de comida mexicana, un acierto total!! Me encantó.  Eché de menos la nata en el desayuno, para las tortitas, gofres y demás. Aunque había sirope de sobra! Camareros, y recepcionistas, muy atent@os. Especial agradecimiento a Bela, de recepción, siempre muy amable con nosotros.  Volveré, y pronto!!! ,2019-11-01,"nov.","Otoño","Sol Arona Tenerife","Sol"
3   Hotel normalito. Está un poco viejo. Las habitaciones no tienen aire acondicionado. Las animaciones por la noche son muy cortas, están principalmente enfocadas para el turismo extranjero y empiezan muy pronto. En mi opinión, las instalaciones no están a la altura de un hotel de 4 estrellas. Lo que más nos gusto, fue el trato del personal del buffet, destacando al camarero Roberto, que nos hizo una estancia mucho más agradable y amena, siempre con una atención maravillosa en el restaurante, y ayudándonos y recomendándonos en cuanto a las actividades que queríamos realizar en la isla,  demostrando  ser un gran profesional que disfruta de su trabajo y siempre con una sonrisa.,2019-09-01,"sep.","Verano","Sol Arona Tenerife","Sol"
4   Tenemos dos niños pequeños por lo que contratar el hotel con pensión todo incluído nos viene muy cómodo. Por otro lado el hotel está cerca de tiendas, farmacias y una clínica por si hay alguna incidencia. Además el hotel está a 5 minutos a pie de la playa de los Cristianos por lo que es muy conveniente.,2020-02-01,"feb.","Invierno","Sol Arona Tenerife","Sol"
5   habitacion de albergue , 20 metros cuadrados para 5 personas incluyendo un bebé ,cama litera de peligro ,  a 180€ por noche deja que desear , la Directira del hotel incapaz de solucionar nuestro reclamo.  Buen buffet y localización , nada más - no volveremos , rato en un Meliá,2020-01-01,"ene.","Invierno","Sol Arona Tenerife","Sol"
6   Bastante bien para unas vacaciones por el sur, Cerca del muelle y de la playa. Se puede ir a pie por los paseos cercanos, Las habitaciones un poco viejas. Pero si vas a dormir y a disfrutar de la isla. Buena relación calidad-precio,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
7   Tuvimos el lavabo atascado y tuvimos que reclamar varias veces su arreglo. Camas incomodas. Todo muy viejo. El bufet malísimo  y sin variedad. Las animaciones y los horarios pensados para extranjeros solamente. Hay un camarero en el bufet de cena que es un pesado. Solamente hablando mal del hotel y de su administración. Desde luego no volveremos. Fuimos cuando era Princesa Dácil y ha sido una decepción.,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
8   puede parecer en un principio q es de la cadena Melia y asi debio ser en sus comienzos, a dia de hoy es bastante normalito tirando a básico, lo elegi para pasar diez días por eso mismo pensando q tenia la calidad de todo el grupo Melia, incluso antes de reservarlo me dijeron q aplicaban el programa de puntos cosa q no hicieron, por q no se había reservado directamente con ellos, si no a través de un operador(FALLO-MALTRATO AL CLIENTE)pero por teléfono te cuentan lo q quieres oir......el bufett es bastante bueno todo hay q decirlo y en cuanto a las habitaciones normalitas sin lujos pero limpias y en buen estado ,2019-01-01,"ene.","Invierno","Sol Arona Tenerife","Sol"
9   Nos alojamos un fin de semana en régimen de todo incluido y la experiencia no fue mala exceptuando algunas cosas. La habitación era grande y espaciosa, además estaba todo muy limpio. Lo malo es que la cama era muy incómoda y con muchos muelles, pero nos lo solucionaron ese mismo día y pudimos dormir decentemente. A pesar de ello, creo que un hotel de estas características debería tener una cama mucho mejor.  Nos vamos descontentos con el tema del todo incluido. Las bebidas eran muy malas. La comida no estaba mala de sabor, pero faltaba variedad en el almuerzo ya que durante los días que estuvimos comimos casi lo mismo. En la cena si que ponían algo más diferente. Los desayunos estaban muy bien pero desde las 10 empiezan a quitar las comida, algo que creo que no debería suceder…,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
10  No es la primera vez que me hospedo por lo que me parece
</code>```

Would greatly appreciate some help with this error as I am not able to solve it. Thank you in advance1

答:
Sounds like the separator in your csv file is different to the one being used by read.csv, which is "" by default.  Perhaps you need, sep=",". But, as @jay.sf says, it's impossible to be sure without seeing your input data.

To specify a different separator in a call to lapply try

```<code>... lapply(function(x) read_csv(x, sep=",")) ...
</code>```

For more information, pleaseread the online documentaion: ?read.csv should give you all you need.

Here's a simple-self contained example showing you how to use read.csv with lapply.  if you still have problems after using this approach, then the problem lies in your source data.  There's little more we can do without seeing your input files.

```<code>library(tidyverse)

d1 <- tibble(x=runif(5), y=runif(5))
d2 <- tibble(x=runif(5), y=runif(5))
d3 <- tibble(x=runif(5), y=runif(5))
# write.csv uses "," as the separator by default
write.csv(d1, "d1.csv")
write.csv(d2, "d2.csv")
write.csv(d3, "d3.csv")

# Using .Platform$file.sep as it looks like you're using Windows and I'm using OS X
lapply(1:3, function(x) read.csv(paste0(getwd(), .Platform$file.sep, "d", x, ".csv"), sep=",")) %>% bind_rows()
</code>```

Giving

```<code>   X         x          y
1  1 0.9252148 0.56729752
2  2 0.5308788 0.16184362
3  3 0.3117391 0.98391774
4  4 0.7920537 0.09282097
5  5 0.9170348 0.19527942
6  1 0.5205679 0.53923853
7  2 0.8024267 0.45252059
8  3 0.9495656 0.42110252
9  4 0.9276184 0.71073388
10 5 0.6631055 0.99259850
11 1 0.9946208 0.52989414
12 2 0.8580251 0.69050776
13 3 0.5421475 0.26334383
14 4 0.9130681 0.15021119
15 5 0.3810522 0.08094137
</code>```

Body:
I have used the following function to create a unique data_frame with csv's (already encoded in UTF-8 form):

library(readr)
comentarios_hoteles<-list.files(path="C:/Users/OneDrive/Documentos/DFBA/ Melia", pattern="*.csv", full.names=TRUE) %>%
  lapply(read_csv)%>%
  bind_rows

For some reason I am getting all the observations in one column instead of in 6.

This is the full code:
Comentario,"Fecha","Mes","Estación","Hotel","Marca"
1   No todas las instalaciones del hotel se pudieron usar, estaban cerradas sin avisar previamente al cliente. Se intentó hacer un cambio en las fechas de la reserva debido al temporal de calima que hubo (no porque no quisiéramos irnos de hotel) y no dejaron (añadiendo que el tiempo estaba mucho mejor que el día anterior) y tampoco propusieron solución. Al llegar al hotel, vemos que la piscina está cerrada por dicho temporal, por lo que encima no se podía disfrutar de todas las instalaciones. Los desayunos muy bien, variados. No puedo decir lo mismo de las cenas: arroz pasado y con olor, poca variedad y para colmo los camareros sirviéndose la cena sin darte paso a ti, cliente, a servite no siendo que le quitaramos el trozo de pizza que quería... En fin... Yo siempre que voy a hotel, voy a los Melia, pero este en concreto no está a la altura de lo que acostumbra la marca, por lo que no lo recomendaría. …,2020-02-01,"feb.","Invierno","Sol Arona Tenerife","Sol"
2   Me he ido con un buen sabor de boca, y ganas de volver. Me ha sorprendido totalmente el hotel.  Nuestra habitación en la planta 14, era genial! Espaciosa, bien cuidada, vistas preciosas, limpieza bien.  Servicio de restaurante con horario amplio. El día de comida mexicana, un acierto total!! Me encantó.  Eché de menos la nata en el desayuno, para las tortitas, gofres y demás. Aunque había sirope de sobra! Camareros, y recepcionistas, muy atent@os. Especial agradecimiento a Bela, de recepción, siempre muy amable con nosotros.  Volveré, y pronto!!! ,2019-11-01,"nov.","Otoño","Sol Arona Tenerife","Sol"
3   Hotel normalito. Está un poco viejo. Las habitaciones no tienen aire acondicionado. Las animaciones por la noche son muy cortas, están principalmente enfocadas para el turismo extranjero y empiezan muy pronto. En mi opinión, las instalaciones no están a la altura de un hotel de 4 estrellas. Lo que más nos gusto, fue el trato del personal del buffet, destacando al camarero Roberto, que nos hizo una estancia mucho más agradable y amena, siempre con una atención maravillosa en el restaurante, y ayudándonos y recomendándonos en cuanto a las actividades que queríamos realizar en la isla,  demostrando  ser un gran profesional que disfruta de su trabajo y siempre con una sonrisa.,2019-09-01,"sep.","Verano","Sol Arona Tenerife","Sol"
4   Tenemos dos niños pequeños por lo que contratar el hotel con pensión todo incluído nos viene muy cómodo. Por otro lado el hotel está cerca de tiendas, farmacias y una clínica por si hay alguna incidencia. Además el hotel está a 5 minutos a pie de la playa de los Cristianos por lo que es muy conveniente.,2020-02-01,"feb.","Invierno","Sol Arona Tenerife","Sol"
5   habitacion de albergue , 20 metros cuadrados para 5 personas incluyendo un bebé ,cama litera de peligro ,  a 180€ por noche deja que desear , la Directira del hotel incapaz de solucionar nuestro reclamo.  Buen buffet y localización , nada más - no volveremos , rato en un Meliá,2020-01-01,"ene.","Invierno","Sol Arona Tenerife","Sol"
6   Bastante bien para unas vacaciones por el sur, Cerca del muelle y de la playa. Se puede ir a pie por los paseos cercanos, Las habitaciones un poco viejas. Pero si vas a dormir y a disfrutar de la isla. Buena relación calidad-precio,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
7   Tuvimos el lavabo atascado y tuvimos que reclamar varias veces su arreglo. Camas incomodas. Todo muy viejo. El bufet malísimo  y sin variedad. Las animaciones y los horarios pensados para extranjeros solamente. Hay un camarero en el bufet de cena que es un pesado. Solamente hablando mal del hotel y de su administración. Desde luego no volveremos. Fuimos cuando era Princesa Dácil y ha sido una decepción.,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
8   puede parecer en un principio q es de la cadena Melia y asi debio ser en sus comienzos, a dia de hoy es bastante normalito tirando a básico, lo elegi para pasar diez días por eso mismo pensando q tenia la calidad de todo el grupo Melia, incluso antes de reservarlo me dijeron q aplicaban el programa de puntos cosa q no hicieron, por q no se había reservado directamente con ellos, si no a través de un operador(FALLO-MALTRATO AL CLIENTE)pero por teléfono te cuentan lo q quieres oir......el bufett es bastante bueno todo hay q decirlo y en cuanto a las habitaciones normalitas sin lujos pero limpias y en buen estado ,2019-01-01,"ene.","Invierno","Sol Arona Tenerife","Sol"
9   Nos alojamos un fin de semana en régimen de todo incluido y la experiencia no fue mala exceptuando algunas cosas. La habitación era grande y espaciosa, además estaba todo muy limpio. Lo malo es que la cama era muy incómoda y con muchos muelles, pero nos lo solucionaron ese mismo día y pudimos dormir decentemente. A pesar de ello, creo que un hotel de estas características debería tener una cama mucho mejor.  Nos vamos descontentos con el tema del todo incluido. Las bebidas eran muy malas. La comida no estaba mala de sabor, pero faltaba variedad en el almuerzo ya que durante los días que estuvimos comimos casi lo mismo. En la cena si que ponían algo más diferente. Los desayunos estaban muy bien pero desde las 10 empiezan a quitar las comida, algo que creo que no debería suceder…,2019-12-01,"dic.","Invierno","Sol Arona Tenerife","Sol"
10  No es la primera vez que me hospedo por lo que me parece

Would greatly appreciate some help with this error as I am not able to solve it. Thank you in advance1

Body:
Sounds like the separator in your csv file is different to the one being used by read.csv, which is "" by default.  Perhaps you need, sep=",". But, as @jay.sf says, it's impossible to be sure without seeing your input data.

To specify a different separator in a call to lapply try

... lapply(function(x) read_csv(x, sep=",")) ...

For more information, pleaseread the online documentaion: ?read.csv should give you all you need.

Here's a simple-self contained example showing you how to use read.csv with lapply.  if you still have problems after using this approach, then the problem lies in your source data.  There's little more we can do without seeing your input files.

library(tidyverse)

d1 <- tibble(x=runif(5), y=runif(5))
d2 <- tibble(x=runif(5), y=runif(5))
d3 <- tibble(x=runif(5), y=runif(5))
# write.csv uses "," as the separator by default
write.csv(d1, "d1.csv")
write.csv(d2, "d2.csv")
write.csv(d3, "d3.csv")

# Using .Platform$file.sep as it looks like you're using Windows and I'm using OS X
lapply(1:3, function(x) read.csv(paste0(getwd(), .Platform$file.sep, "d", x, ".csv"), sep=",")) %>% bind_rows()

Giving

   X         x          y
1  1 0.9252148 0.56729752
2  2 0.5308788 0.16184362
3  3 0.3117391 0.98391774
4  4 0.7920537 0.09282097
5  5 0.9170348 0.19527942
6  1 0.5205679 0.53923853
7  2 0.8024267 0.45252059
8  3 0.9495656 0.42110252
9  4 0.9276184 0.71073388
10 5 0.6631055 0.99259850
11 1 0.9946208 0.52989414
12 2 0.8580251 0.69050776
13 3 0.5421475 0.26334383
14 4 0.9130681 0.15021119
15 5 0.3810522 0.08094137


问:
LINQ: Search/Filter data from multiple table
I have three tables,

Table:1

```<code> UserId  UserName     ...
  1      Jhon        ...
  2      Ashley      ...
  3      Alexa       ...
  4      Krish       ...
</code>```

Table:2

```<code>BrandId UserId  BrandName
 1       1       BMW
 2       1       Citroen
 3       2       Audi
 4       4       Peugeot
</code>```

Table:3

```<code>CountryId UserId  CountryName
 1          3       Austria
</code>```

Now what I want if user search items by Brands = ["BMW", "Audi"] & Countries= ["India","Romania"] then it should show the user result like :

```<code> UserId  UserName     ...
  1      Jhon        ...
  2      Ashley      ...
</code>```

or search items by only Countries= ["India","Austria"] then result should be :

```<code> UserId  UserName     ...
   3      Alexa       ...
</code>```

I have tried like following C#-LINQ, But I am always getting all user data. It's not filtering based on the given Brand or Country input. So it should give the data if either Brands or Countries match with DB data.  It's not giving properly even if I remove the "into" from the LINQ part. Where Did I go wrong?

```<code> var users = new List<Users>();
 users = _DbContext.Users.Where(x => x.Roles == model.Role).ToList();
 users = (from p in users
                         join b in _DbContext.UserBrands.Where(x => model.arBrands.Contains(x.BrandName)).ToList() on p.UserSequence equals b.UserId into bg
                         join c in _DbContext.UserCountries.Where(x => model.arCountries.Contains(x.CountryName)).ToList() on p.UserSequence equals c.UserId into cg
                         select p).ToList();
</code>```

And my Sample Payload,

```<code>{
 "arBrands": ["Citroen","Peugeot"],
 "arCountries":["India","Romania"],
 "Role":"All Roles"
}
</code>```

Entities:

```<code>public class UserBrands
{
    [Key] public virtual int UserBrandsId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int BrandId { get; set; }
    public virtual string BrandName { get; set; }
}

public class UserCountries
{
    [Key] public virtual int UserCountriesId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int CountryId { get; set; }
    public virtual string CountryName { get; set; }
}

public class UsersModel
{
    public string[] arCountries { get; set; }
    public string[] arBrands { get; set; }
    [Required]
    public string Role { get; set; }
    public List<LeafLet> features { get; set; }
}

public class Users : BaseEntity
{
    [Key]
    public virtual int UserSequence { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Countries { get; set; }
    public virtual string Brands { get; set; }
    public virtual string Email { get; set; }
    public virtual string Latitude { get; set; }
    public virtual string Longitude { get; set; }
    public virtual string ProjectRole { get; set; }
    public virtual string Roles { get; set; }
}
</code>```

答:
You will need to clean up your models a bit, and add navigation properties to let EF perform the joins for you.

```<code>    public class Users
    {
        [Key]
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Role { get; set; }

        //Only use the virtual keyword for navigating properties to other entities.
        public virtual IEnumerable<UserBrand> UserBrands {get; set;}
        public virtual IEnumerable<UserCountry> UserCountries {get; set;}
    }

    public class UserBrand
    {
        [Key]
        public int Id { get; set; }
        public int UserId { get; set; }
        public int BrandId { get; set; }

        [ForeignKey("UserId")] // lets Entity Framework know how to map the navigation.
        public virtual User User { get; set; }

        [ForeignKey("BrandId")]
        public virtual Brand Brand { get; set; }
    }

    public class Brand
    {
        [Key]
        public int Id { get; set; }
        public string BrandName { get; set; }
    }

    public class UserCountry
    {
        [Key]
        public int Id { get; set; }
        public int UserId { get; set; }
        public int CountryId { get; set; }

        [ForeignKey("UserId")]
        public virtual User User { get; set; }

        [ForeignKey("CountryId")]
        public virtual Country Country { get; set; }
    }

    public class Country
    {
        [Key]
        public int Id { get; set; }
        public string CountryName { get; set; }
    }
</code>```

Your LINQ query will then look something like this:

```<code> var users = _DbContext.Users
                 .Where(u => u.Role == model.Role)
                 .Select(u => new {
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.UserBrands.Select(ub => ub.Brand.BrandName),
                      Countries = u.UserCountries.Select(uc => uc.CountryName)
                  }).ToList();
</code>```

You can add more filters to the Where clause using the navigation properties:

```<code> var users = _DbContext.Users
                 .Where(u => u.Role == model.Role
                       && u.UserBrands.Any(ub =>
                              ub.Brand.BrandName == "Brand X") //Filter for brand name.
                       && u.UserCountries.Any(uc =>
                              uc.Country.CountryName == "United States") //Filter for brand name.

                 .Select(u => new {
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.BrandNames,
                      Countries = u.Countries
                           })
                 .ToList();
</code>```

Body:
I have three tables,

Table:1

 UserId  UserName     ...
  1      Jhon        ...
  2      Ashley      ...
  3      Alexa       ...
  4      Krish       ...

Table:2

BrandId UserId  BrandName
 1       1       BMW
 2       1       Citroen
 3       2       Audi
 4       4       Peugeot

Table:3

CountryId UserId  CountryName
 1          3       Austria

Now what I want if user search items by Brands = ["BMW", "Audi"] & Countries= ["India","Romania"] then it should show the user result like :

 UserId  UserName     ...
  1      Jhon        ...
  2      Ashley      ...

or search items by only Countries= ["India","Austria"] then result should be :

 UserId  UserName     ...
   3      Alexa       ...

I have tried like following C#-LINQ, But I am always getting all user data. It's not filtering based on the given Brand or Country input. So it should give the data if either Brands or Countries match with DB data.  It's not giving properly even if I remove the "into" from the LINQ part. Where Did I go wrong?

 var users = new List<Users>();
 users = _DbContext.Users.Where(x => x.Roles == model.Role).ToList();
 users = (from p in users
                         join b in _DbContext.UserBrands.Where(x => model.arBrands.Contains(x.BrandName)).ToList() on p.UserSequence equals b.UserId into bg
                         join c in _DbContext.UserCountries.Where(x => model.arCountries.Contains(x.CountryName)).ToList() on p.UserSequence equals c.UserId into cg
                         select p).ToList();

And my Sample Payload,

{
 "arBrands": ["Citroen","Peugeot"],
 "arCountries":["India","Romania"],
 "Role":"All Roles"
}

Entities:

public class UserBrands
{
    [Key] public virtual int UserBrandsId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int BrandId { get; set; }
    public virtual string BrandName { get; set; }
}

public class UserCountries
{
    [Key] public virtual int UserCountriesId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int CountryId { get; set; }
    public virtual string CountryName { get; set; }
}

public class UsersModel
{
    public string[] arCountries { get; set; }
    public string[] arBrands { get; set; }
    [Required]
    public string Role { get; set; }
    public List<LeafLet> features { get; set; }
}

public class Users : BaseEntity
{
    [Key]
    public virtual int UserSequence { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Countries { get; set; }
    public virtual string Brands { get; set; }
    public virtual string Email { get; set; }
    public virtual string Latitude { get; set; }
    public virtual string Longitude { get; set; }
    public virtual string ProjectRole { get; set; }
    public virtual string Roles { get; set; }
}

Body:
You will need to clean up your models a bit, and add navigation properties to let EF perform the joins for you.

    public class Users
    {
        [Key]
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Role { get; set; }

        //Only use the virtual keyword for navigating properties to other entities.
        public virtual IEnumerable<UserBrand> UserBrands {get; set;}
        public virtual IEnumerable<UserCountry> UserCountries {get; set;}
    }

    public class UserBrand
    {
        [Key]
        public int Id { get; set; }
        public int UserId { get; set; }
        public int BrandId { get; set; }

        [ForeignKey("UserId")] // lets Entity Framework know how to map the navigation.
        public virtual User User { get; set; }

        [ForeignKey("BrandId")]
        public virtual Brand Brand { get; set; }
    }

    public class Brand
    {
        [Key]
        public int Id { get; set; }
        public string BrandName { get; set; }
    }

    public class UserCountry
    {
        [Key]
        public int Id { get; set; }
        public int UserId { get; set; }
        public int CountryId { get; set; }

        [ForeignKey("UserId")]
        public virtual User User { get; set; }

        [ForeignKey("CountryId")]
        public virtual Country Country { get; set; }
    }

    public class Country
    {
        [Key]
        public int Id { get; set; }
        public string CountryName { get; set; }
    }

Your LINQ query will then look something like this:

 var users = _DbContext.Users
                 .Where(u => u.Role == model.Role)
                 .Select(u => new {
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.UserBrands.Select(ub => ub.Brand.BrandName),
                      Countries = u.UserCountries.Select(uc => uc.CountryName)
                  }).ToList();

You can add more filters to the Where clause using the navigation properties:

 var users = _DbContext.Users
                 .Where(u => u.Role == model.Role
                       && u.UserBrands.Any(ub =>
                              ub.Brand.BrandName == "Brand X") //Filter for brand name.
                       && u.UserCountries.Any(uc =>
                              uc.Country.CountryName == "United States") //Filter for brand name.

                 .Select(u => new {
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.BrandNames,
                      Countries = u.Countries
                           })
                 .ToList();


问:
How to rename a date frame in a list as it is written in the first column of each list in R?
I have a large list with more than 100 data frames in it. For simplification I show a list with three data frames ("dummy data). I would like to name each data frame as it is written in the first column. In my example I would like to rename DF1 to TGX. The same for DF2 to TBF and DF3 to TZW.

```<code># dummy data
listDF <- list(
  DF1 = data.frame(
    sample = c("TGX", "TGX", "TGX", "TGX"),
    RC = c(0, 1, 2, 3),
    medRC = c(0, 3, 4, 0),
    RC.norm = c(0, 3, 3, 3),
    medRC.norm = c(0, 3, 3, 3)
  ),
  DF2 = data.frame(
    sample = c("TBF", "TBF", "TBF", "TBF"),
    RC = c(2, 1, 2, 3),
    medRC = c(4, 3, 4, 0),
    RC.norm = c(1, 3, 3, 3),
    medRC.norm = c(0, 3, 3, 3)
  ),
  DF3 = data.frame(
    sample = c("TZW", "TZW", "TZW", "TZW"),
    RC = c(4, 3, 2, 3),
    medRC = c(1, 3, 2, 0),
    RC.norm = c(1, 1, 1, 1),
    medRC.norm = c(0, 7, 5, 3)
  )
)
</code>```

```<code>    listDF

    # $DF1
    #   sample  RC medRC RC.norm medRC.norm
    # 1  TGX    0     0       0          0
    # 2  TGX    1     3       3          3
    # 3  TGX    2     4       3          3
    # 4  TGX    3     0       3          3

    # $DF2
    #   sample RC medRC RC.norm medRC.norm
    # 1  TBF   2     4       1       0
    # 3  TBF   1     3       3       3
    # 4  TBF   2     4       3       3
    # 5  TBF   3     0       3       3

    # $DF3
    #   sample  RC medRC RC.norm medRC.norm
    # 1  TZW    4     1       1          0
    # 2  TZW    3     3       1          7
    # 3  TZW    2     2       1          5
    # 4  TZW    3     0       1          3
</code>```

答:
You can extract the first cell value from each dataframe and rename :</p>

```<code>names(listDF) <- sapply(listDF, function(x) x[1, 1])

listDF
#$TGX
#  sample RC medRC RC.norm medRC.norm
#1    TGX  0     0       0          0
#2    TGX  1     3       3          3
#3    TGX  2     4       3          3
#4    TGX  3     0       3          3

#$TBF
#  sample RC medRC RC.norm medRC.norm
#1    TBF  2     4       1          0
#2    TBF  1     3       3          3
#3    TBF  2     4       3          3
#4    TBF  3     0       3          3

#$TZW
#  sample RC medRC RC.norm medRC.norm
#1    TZW  4     1       1          0
#2    TZW  3     3       1          7
#3    TZW  2     2       1          5
#4    TZW  3     0       1          3
</code>```

Body:
I have a large list with more than 100 data frames in it. For simplification I show a list with three data frames ("dummy data). I would like to name each data frame as it is written in the first column. In my example I would like to rename DF1 to TGX. The same for DF2 to TBF and DF3 to TZW.

# dummy data
listDF <- list(
  DF1 = data.frame(
    sample = c("TGX", "TGX", "TGX", "TGX"),
    RC = c(0, 1, 2, 3),
    medRC = c(0, 3, 4, 0),
    RC.norm = c(0, 3, 3, 3),
    medRC.norm = c(0, 3, 3, 3)
  ),
  DF2 = data.frame(
    sample = c("TBF", "TBF", "TBF", "TBF"),
    RC = c(2, 1, 2, 3),
    medRC = c(4, 3, 4, 0),
    RC.norm = c(1, 3, 3, 3),
    medRC.norm = c(0, 3, 3, 3)
  ),
  DF3 = data.frame(
    sample = c("TZW", "TZW", "TZW", "TZW"),
    RC = c(4, 3, 2, 3),
    medRC = c(1, 3, 2, 0),
    RC.norm = c(1, 1, 1, 1),
    medRC.norm = c(0, 7, 5, 3)
  )
)

    listDF

    # $DF1
    #   sample  RC medRC RC.norm medRC.norm
    # 1  TGX    0     0       0          0
    # 2  TGX    1     3       3          3
    # 3  TGX    2     4       3          3
    # 4  TGX    3     0       3          3

    # $DF2
    #   sample RC medRC RC.norm medRC.norm
    # 1  TBF   2     4       1       0
    # 3  TBF   1     3       3       3
    # 4  TBF   2     4       3       3
    # 5  TBF   3     0       3       3

    # $DF3
    #   sample  RC medRC RC.norm medRC.norm
    # 1  TZW    4     1       1          0
    # 2  TZW    3     3       1          7
    # 3  TZW    2     2       1          5
    # 4  TZW    3     0       1          3

Body:
You can extract the first cell value from each dataframe and rename :

names(listDF) <- sapply(listDF, function(x) x[1, 1])

listDF
#$TGX
#  sample RC medRC RC.norm medRC.norm
#1    TGX  0     0       0          0
#2    TGX  1     3       3          3
#3    TGX  2     4       3          3
#4    TGX  3     0       3          3

#$TBF
#  sample RC medRC RC.norm medRC.norm
#1    TBF  2     4       1          0
#2    TBF  1     3       3          3
#3    TBF  2     4       3          3
#4    TBF  3     0       3          3

#$TZW
#  sample RC medRC RC.norm medRC.norm
#1    TZW  4     1       1          0
#2    TZW  3     3       1          7
#3    TZW  2     2       1          5
#4    TZW  3     0       1          3


问:
Where to find photos
I use pycharm and I run the code from github.
where can I get the word-cloud image?

```<code>#!/usr/bin/env python
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""

import os

from os import path
from wordcloud import WordCloud

# get data directory (using getcwd() is needed to support running example in generated IPython notebook)
d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()

# Read the whole text.
text = open(path.join(d, 'crawling.xlsx')).read()  #I used my text. Only here was corrected.

# Generate a word cloud image
wordcloud = WordCloud().generate(text)

# Display the generated image:
# the matplotlib way:
import matplotlib.pyplot as plt
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")

# lower max_font_size
wordcloud = WordCloud(max_font_size=40).generate(text)
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

# The pil way (if you don't have matplotlib)
image = wordcloud.to_image()
image.show()
</code>```

And I wonder if separate tokenization or string cleansing is required when using the word cloud library.

答:
Add this one line to the end to save the image:

```<code>image.save("constitution.png")
</code>```

See Pillow reference for Image.save.

Title: Where to find photos

Body:
I use pycharm and I run the code from github.
where can I get the word-cloud image?

#!/usr/bin/env python
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""

import os

from os import path
from wordcloud import WordCloud

# get data directory (using getcwd() is needed to support running example in generated IPython notebook)
d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()

# Read the whole text.
text = open(path.join(d, 'crawling.xlsx')).read()  #I used my text. Only here was corrected.

# Generate a word cloud image
wordcloud = WordCloud().generate(text)

# Display the generated image:
# the matplotlib way:
import matplotlib.pyplot as plt
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")

# lower max_font_size
wordcloud = WordCloud(max_font_size=40).generate(text)
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

# The pil way (if you don't have matplotlib)
image = wordcloud.to_image()
image.show()

And I wonder if separate tokenization or string cleansing is required when using the word cloud library.

Body:
Add this one line to the end to save the image:

image.save("constitution.png")

See Pillow reference for Image.save.