Example #1
0
	/*
	 * Adding an agent means placing them into our PQ.  If agent
	 * remove ts is < PQ->min, then must update LP remove timer.
	 *
	 * Check time for stage change.  Place in queue by minimum
	 * stage change time or remove time.  Set timer for stage
	 * change time (and event) or remove time (and event).
	 */
void
epi_agent_add(epi_state * state, tw_bf * bf, tw_memory * buf, tw_lp * lp)
{
	epi_agent	*a;

	a = tw_memory_data(buf);

	if(5 == a->id && 0)
		printf("%lld: added %d at %lf \n", lp->gid, a->id && 0, tw_now(lp));

	// Test to make sure this location is this lp
	if (lp->gid != a->loc[a->curr])
		tw_error(TW_LOC, "epi_agent_add adding agent to lp %d but loc[%d] is %d",
			 lp->gid, a->curr, a->loc[a->curr]);

	// if agent is contagious, increment number of contagious agents here
	epi_agent_contagious(state, buf, +1);

	a->ts_remove = tw_now(lp) + a->dur[a->curr];
	epi_agent_update_ts(state, bf, a, lp);

	pq_enqueue(g_epi_pq[lp->id], buf);

	if(pq_get_size(g_epi_pq[lp->id]) > state->max_queue_size)
		state->max_queue_size = pq_get_size(g_epi_pq[lp->id]);

	// If not at home, if agent is a worried well, if there are already enough symtomatic
	// people here then starting tomorrow, this agent will stay home for the number
	// of days remaining.  days_remaining is checked in agent_remove().
	
	if(!a->days_remaining && a->nloc > 1 && a->loc[a->curr] != a->loc[0] && 
		(a->behavior_flags & EPI_AGENT_WORRIED_WELL))
	{
		if ((float) state->ncontagious_tot / (float) state->max_queue_size > 
				g_epi_ww_threshold)
		{
			a->days_remaining = g_epi_ww_duration;
			a->behavior_flags = 0;
			g_epi_hospital_ww[state->hospital][0]++;
		}
	}
}
int main( int argc, char** argv )
{
    uint64_t i;

    // pointers for casting
    pq_op_create *op_create;
    pq_op_destroy *op_destroy;
    pq_op_clear *op_clear;
    pq_op_get_key *op_get_key;
    pq_op_get_item *op_get_item;
    pq_op_get_size *op_get_size;
    pq_op_insert *op_insert;
    pq_op_find_min *op_find_min;
    pq_op_delete *op_delete;
    pq_op_delete_min *op_delete_min;
    pq_op_decrease_key *op_decrease_key;
    //pq_op_meld *op_meld;
    pq_op_empty *op_empty;

    // temp dummies for readability
    pq_type *q;//, *r;
    pq_node_type *n;

    if( argc < 2 )
        exit( -1 );

    int trace_file = open( argv[1], O_RDONLY );
    if( trace_file < 0 )
    {
        fprintf( stderr, "Could not open file.\n" );
        return -1;
    }

    pq_trace_header header;
    pq_trace_read_header( trace_file, &header );
    close( trace_file );

    //printf("Header: (%llu,%lu,%lu)\n",header.op_count,header.pq_ids,
    //    header.node_ids);

    pq_op_blank *ops = calloc( MIN( header.op_count, CHUNK_SIZE ),
        sizeof( pq_op_blank ) );
    pq_type **pq_index = calloc( header.pq_ids, sizeof( pq_type* ) );
    pq_node_type **node_index = calloc( header.node_ids,
        sizeof( pq_node_type* ) );
    if( ops == NULL || pq_index == NULL || node_index == NULL )
    {
        fprintf( stderr, "Calloc fail.\n" );
        return -1;
    }

#ifdef USE_QUAKE
    mem_capacities[0] = header.node_ids << 2;
#else
    mem_capacities[0] = header.node_ids;
#endif

#ifdef USE_EAGER
    mem_map *map = mm_create( mem_types, mem_sizes, mem_capacities );
#else
    mem_map *map = mm_create( mem_types, mem_sizes );
#endif

    uint64_t op_remaining, op_chunk;
    int status;
    struct timeval t0, t1;
    uint32_t iterations = 0;
    uint32_t total_time = 0;
    key_type k;
    //pq_node_type *min;

#ifndef CACHEGRIND
    while( iterations < 5 || total_time < PQ_MIN_USEC )
    {
        mm_clear( map );
        iterations++;
#endif

        trace_file = open( argv[1], O_RDONLY );
        if( trace_file < 0 )
        {
            fprintf( stderr, "Could not open file.\n" );
            return -1;
        }
        pq_trace_read_header( trace_file, &header );
        op_remaining = header.op_count;

        while( op_remaining > 0 )
        {
            op_chunk = MIN( CHUNK_SIZE, op_remaining );
            op_remaining -= op_chunk;

            for( i = 0; i < op_chunk; i++ )
            {
                status = pq_trace_read_op( trace_file, ops + i );
                if( status == -1 )
                {
                    fprintf( stderr, "Invalid operation!" );
                    return -1;
                }
            }

#ifndef CACHEGRIND
            gettimeofday(&t0, NULL);
#endif

            for( i = 0; i < op_chunk; i++ )
            {
                switch( ops[i].code )
                {
                    case PQ_OP_CREATE:
                        op_create = (pq_op_create*) ( ops + i );
                        //printf("pq_create(%d)\n", op_create->pq_id);
                        pq_index[op_create->pq_id] = pq_create( map );
                        break;
                    case PQ_OP_DESTROY:
                        op_destroy = (pq_op_destroy*) ( ops + i );
                        //printf("pq_destroy(%d)\n", op_destroy->pq_id);
                        q = pq_index[op_destroy->pq_id];
                        pq_destroy( q );
                        pq_index[op_destroy->pq_id] = NULL;
                        break;
                    case PQ_OP_CLEAR:
                        op_clear = (pq_op_clear*) ( ops + i );
                        //printf("pq_clear(%d)\n", op_clear->pq_id );
                        q = pq_index[op_clear->pq_id];
                        pq_clear( q );
                        break;
                    case PQ_OP_GET_KEY:
                        op_get_key = (pq_op_get_key*) ( ops + i );
                        //printf("pq_get_key(%d,%d)\n", op_get_key->pq_id,
                        //    op_get_key->node_id );
                        q = pq_index[op_get_key->pq_id];
                        n = node_index[op_get_key->node_id];
                        pq_get_key( q, n );
                        break;
                    case PQ_OP_GET_ITEM:
                        op_get_item = (pq_op_get_item*) ( ops + i );
                        //printf("pq_get_item(%d,%d)\n", op_get_item->pq_id,
                        //    op_get_item->node_id);
                        q = pq_index[op_get_item->pq_id];
                        n = node_index[op_get_item->node_id];
                        pq_get_item( q, n );
                        break;
                    case PQ_OP_GET_SIZE:
                        op_get_size = (pq_op_get_size*) ( ops + i );
                        //printf("pq_get_size(%d)\n", op_get_size->pq_id);
                        q = pq_index[op_get_size->pq_id];
                        pq_get_size( q );
                        break;
                    case PQ_OP_INSERT:
                        op_insert = (pq_op_insert*) ( ops + i );
                        //printf("pq_insert(%d,%d,%llu,%d)\n", op_insert->pq_id,
                        //    op_insert->node_id, op_insert->key, op_insert->item );
                        q = pq_index[op_insert->pq_id];
                        node_index[op_insert->node_id] = pq_insert( q,
                            op_insert->item, op_insert->key );
                        break;
                    case PQ_OP_FIND_MIN:
                        op_find_min = (pq_op_find_min*) ( ops + i );
                        //printf("pq_find_min(%d)\n", op_find_min->pq_id );
                        q = pq_index[op_find_min->pq_id];
                        pq_find_min( q );
                        break;
                    case PQ_OP_DELETE:
                        op_delete = (pq_op_delete*) ( ops + i );
                        //printf("pq_delete(%d,%d)\n", op_delete->pq_id,
                        //    op_delete->node_id );
                        q = pq_index[op_delete->pq_id];
                        n = node_index[op_delete->node_id];
                        pq_delete( q, n );
                        break;
                    case PQ_OP_DELETE_MIN:
                        op_delete_min = (pq_op_delete_min*) ( ops + i );
                        //printf("pq_delete_min(%d)\n", op_delete_min->pq_id);
                        q = pq_index[op_delete_min->pq_id];
                        //min = pq_find_min( q );
                        k = pq_delete_min( q );
#ifdef CACHEGRIND
                        if( argc > 2 )
                            printf("%llu\n",k);
#endif
                        break;
                    case PQ_OP_DECREASE_KEY:
                        op_decrease_key = (pq_op_decrease_key*) ( ops + i );
                        //printf("pq_decrease_key(%d,%d,%llu)\n", op_decrease_key->pq_id,
                        //    op_decrease_key->node_id, op_decrease_key->key);
                        q = pq_index[op_decrease_key->pq_id];
                        n = node_index[op_decrease_key->node_id];
                        pq_decrease_key( q, n, op_decrease_key->key );
                        break;
                    /*case PQ_OP_MELD:
                        printf("Meld.\n");
                        op_meld = (pq_op_meld*) ( ops + i );
                        q = pq_index[op_meld->pq_src1_id];
                        r = pq_index[op_meld->pq_src2_id];
                        pq_index[op_meld->pq_dst_id] = pq_meld( q, r );
                        break;*/
                    case PQ_OP_EMPTY:
                        op_empty = (pq_op_empty*) ( ops + i );
                        //printf("pq_empty(%d)\n", op_empty->pq_id);
                        q = pq_index[op_empty->pq_id];
                        pq_empty( q );
                        break;
                    default:
                        break;
                }
                //verify_queue( pq_index[0], header.node_ids );
            }

#ifndef CACHEGRIND
            gettimeofday(&t1, NULL);
            total_time += (t1.tv_sec - t0.tv_sec) * 1000000 +
                (t1.tv_usec - t0.tv_usec);
#endif
        }

        close( trace_file );
#ifndef CACHEGRIND
    }
#endif

    for( i = 0; i < header.pq_ids; i++ )
    {
        if( pq_index[i] != NULL )
            pq_destroy( pq_index[i] );
    }

    mm_destroy( map );
    free( pq_index );
    free( node_index );
    free( ops );

#ifndef CACHEGRIND
    printf( "%d\n", total_time / iterations );
#endif

    return 0;
}
Example #3
0
/*
 * epi_seir_compute: compute SEIR model for all agents in location LPn
 *
 * Assume that the probability of catching the disease is constant over time.
 * If the probability of catching the disease in one hour is P, then the
 * geometric distribution gives the number of hours before the disease is
 * caught.  We do a draw on the random number generator from the geometric
 * distribution and if the result is less than the time interval, then the
 * agent gets sick at that time.
 */
void
epi_seir_compute(epi_state * state, tw_bf * bf, epi_agent * in_a, tw_lp * lp)
{
	/*
	 * For each susceptible agent, for each contagious agent, determine
	 * the susceptible agent caught the disease.
	 */

	double		 draw,
			 delta_t;
	epi_agent	*a, *ai;
	epi_ic_stage	*s, *sn;
	unsigned int	 queue_size;
	unsigned int	 i, j;

	void		*pq;

	queue_size = pq_get_size(state->pq);
	if (queue_size <= 1)
		return;

	delta_t = tw_now(lp) - state->last_event;

	//printf(" lp %2d SEIR delta_t %f at %f\n", (int) lp->id, delta_t, tw_now(lp));

	if (delta_t < EPSILON) // already done an seir check at this time.
		return;

	//printf("SEIR Check %f\n", tw_now(lp));

	pq = state->pq;

	//printf( "Queue size: %d  ", queue_size);

	for ( i = 0; i < queue_size; i++)
	{
		a = (epi_agent *) pq_next( pq, i);
		//printf("\ta: %d, stage: %d\n ", a->id, a->stage);
		if (a->stage == EPI_SUSCEPTIBLE)
		{
			for (j = 0; j < queue_size; j++)
			{
				if ( j == i ) continue;
				ai = (epi_agent *) pq_next(pq, j);
				s = &g_epi_stages[ai->stage];
				//printf("a: %d, ai: %d, ln_multiplier: %f\n", a->id, ai->id, s->ln_multiplier);
				if (abs(s->ln_multiplier) > EPSILON)
				{
					// tw_geometric draws from uniform until the draw is greater than P.
					// tw_geometric then returns the number of draws.
					// For large P (which is 1.0 - multiplier) this could be very large.
					// Also note that tw_geometric always returns an integer of 1 or
					// greater.
					draw = tw_rand_unif(lp->id);

					draw = log(draw);
					draw /= g_epi_stages[a->stage].ln_multiplier;

					//draw = tw_rand_geometric(lp->id, (s->start_multiplier + s->stop_multiplier)/2);
					//state->stats->s_ndraws += draw;
					state->stats->s_nchecked++;
					//printf("SEIR agent %d, stage %d, agent %d, stage %d, draw: %g\n",
					//	a->id, a->stage, ai->id, ai->stage, draw);
					if (draw <= delta_t) //Make agent sick
					{
#if EPI_DEBUG
						printf("%7.3f, lp, %7d, agent_infect, , , , %7d, %5.3f, %5.2f\n",
							tw_now(lp), (int) lp->id, a->id, delta_t, draw);
#endif
						a->stage = EPI_INCUBATING;
						g_epi_ct[a->ct][0]--;
						g_epi_ct[a->ct][1]++;
						if (g_epi_position_f)
							fprintf(g_epi_position_f, "%.3f,%d,%d,%d\n", tw_now(lp), a->id, (int) lp->id, a->stage);

						sn = &g_epi_stages[a->stage];
						a->ts_infected = tw_now(lp);
						a->ts_stage_tran = tw_rand_unif(lp->id)*(sn->max_duration - sn->min_duration)
								+ sn->min_duration + tw_now(lp);
						a->ts_last_tran = tw_now(lp);
						// collect statistics
						state->stats->s_ninfected++;
						break;
					}
#if EPI_DEBUG
					else
					{
						printf("%7.3f, lp, %7d, agent_not_infect, , , , %7d, %5.3f, %5.2f\n",
							tw_now(lp), (int) lp->id, a->id, delta_t, draw);
					}
#endif
				}
			}
		}
	}	
 
	//printf("SEIR compputed at %f ", state->last_event);
}
Example #4
0
/*
 * epi_init - initialize node LPs state variables
 * 
 * state	- our node LP state space
 * lp		- our node LP
 */
void
epi_init(epi_state * state, tw_lp * lp)
{
	tw_memory	*b;
	tw_memory	*agent = NULL;
	tw_stime	 ts_min_tran = DBL_MAX;

	epi_agent	*a;
	epi_pathogen	*p;
	epi_ic_stage	*s;

	double		 x;

	int		 i;
	int		 j;
	int		 sz;

	// hard-coded, single hospital LP
	if(lp->id == g_tw_nlp-1)
	{
		fprintf(g_epi_hospital_f, "0 0 %u %u %u\n", 
			g_epi_hospital[0][0], g_epi_hospital_ww[0][0], 
			g_epi_hospital_wws[0][0]);

		g_epi_hospital[0][0] = 0;
		g_epi_hospital_ww[0][0] = 0;
		g_epi_hospital_wws[0][0] = 0;

		return;
	}

	// ID of the hospital I go to (or nearest if office/school)
	state->hospital = 0;
	state->stats = tw_calloc(TW_LOC, "", sizeof(epi_statistics), 1);
	state->ncontagious = tw_calloc(TW_LOC, "", sizeof(unsigned int), g_epi_ndiseases);
	state->ts_seir = tw_calloc(TW_LOC, "", sizeof(tw_stime), g_epi_ndiseases);

	for(i = 0; i < g_epi_ndiseases; i++)
		state->ts_seir[i] = DBL_MAX;

	// if no agents initially at this location, then we are done!
	if(0 == (sz = pq_get_size(g_epi_pq[lp->id])))
		return;

	// determine agents initial parameters / configuration
	for(i = 0; i < sz; i++)
	{
		agent = pq_next(g_epi_pq[lp->id], i);
		a = tw_memory_data(agent);

		for(j = 0; j < g_epi_ndiseases; j++)
		{
			if(!a->id && !j)
			{
				// ALLOCATE PATHOGEN AND FILL IT IN
				b = tw_memory_alloc(lp, g_epi_pathogen_fd);
				p = tw_memory_data(b);

				b->next = a->pathogens;
				a->pathogens = b;

				p->index = j;
				p->stage = EPI_SUSCEPTIBLE;
				p->ts_stage_tran = DBL_MAX;

				g_epi_regions[a->region][p->index][p->stage]--;
				p->stage = EPI_EXPOSED;
				g_epi_regions[a->region][p->index][p->stage]++;
				g_epi_exposed_today[j]++;
	
				// determine if agents start out sick.
				if(tw_rand_unif(lp->rng) < g_epi_sick_rate)
				{

				s = &g_epi_diseases[p->index].stages[p->stage];

				x = ((double) tw_rand_integer(lp->rng, 0, INT_MAX) / 
						(double) INT_MAX);

				p->ts_stage_tran = (s->min_duration + 
						(x * (s->max_duration - s->min_duration)));

				if(0.0 >= p->ts_stage_tran)
					tw_error(TW_LOC, "Immediate stage transition?!");

				//state->stats->s_ninfected++;
				state->ncontagious[p->index]++;
				state->ncontagious_tot++;
				//g_epi_hospital[0][0]++;
				g_epi_sick_init_pop[j]++;

				ts_min_tran = min(ts_min_tran, p->ts_stage_tran);

				if(!a->id)
					printf("%ld: agent exposed %d: %s, transition at %lf\n", 
					lp->id, a->id, g_epi_diseases[j].name, 
					p->ts_stage_tran);
				}
			}
		}

		// reflect ts_next change in PQ ordering
		if(ts_min_tran < a->ts_next)
		{
			a->ts_next = ts_min_tran;
			pq_delete_any(g_epi_pq[lp->id], &agent);
			pq_enqueue(g_epi_pq[lp->id], agent);
		}

		// determine if agents are a part of worried well population.
		if(g_epi_ww_rate)
		{
			if(tw_rand_unif(lp->rng) < g_epi_ww_rate)
			{
				a->behavior_flags = 1;
				g_epi_hospital_ww[0][0]++;
				g_epi_ww_init_pop++;
			}
		} else if(g_epi_wws_rate)
		{
			if(tw_rand_unif(lp->rng) < g_epi_wws_rate)
			{
				a->behavior_flags = 2;
				g_epi_hospital_wws[0][0]++;
				g_epi_wws_init_pop++;
			}
		}

		// define agent's at work contact population
		//g_epi_regions[a->region][a->stage]++;
	}

	epi_location_timer(state, lp);
}
Example #5
0
/*
 * epi_event_handler - main event processing (per node LP)
 * 
 * state	- our node LP state space
 * bf		- a bitfield provided by the simulation ecxecutive
 * m		- the incoming event or message
 * lp		- our node LP
 */
void
epi_event_handler(epi_state * state, tw_bf * bf, epi_message * msg, tw_lp * lp)
{
	tw_memory	*buf;
	tw_memory	*b;

	epi_agent	*a;

	int		 population;
	int		 ncontagious[g_epi_ndiseases];
	int		 today;
	int		 pq_clean = 0;
	int		 i;

	// TO DO: need to check for last day to get last day of statistics
	today = (int) (tw_now(lp) / TWENTY_FOUR_HOURS);
	population = pq_get_size(g_epi_pq[lp->id]);

	for(i = 0; i < g_epi_ndiseases; i++)
		ncontagious[i] = state->ncontagious[i];

	if(today > g_epi_day)
	{
		// report yesterday's statistics
		epi_report_census_tract(today); 
		epi_report_hospitals(today);

		g_epi_day++;

		printf("%ld: DAY %d \n", lp->id, today);
	}

	if(g_epi_complete)
		return;

	// may return NULL in case of EPI_REMOVE
	if(NULL != (buf = tw_event_memory_get(lp)))
	{
		a = tw_memory_data(buf);

		while(NULL != (b = tw_event_memory_get(lp)))
		{
			b->next = a->pathogens;
			a->pathogens = b;
		}

		epi_agent_add(state, bf, buf, lp);

		printf("%ld: ADD %d at %lf \n", lp->id, a->id, tw_now(lp));
	} else
	{
		epi_agent_remove(state, bf, lp);
	}

	// Bring SEIR computation up to date for the agents at this location
	// Ok to skip if no change to infectious population, 
	// or no change to overall location population
	//
	// basically, avoid calling epi_seir_update, like it was the plague,
	// pun intended.
	for(i = 0; i < g_epi_ndiseases; i++)
	{
		if((population != pq_get_size(g_epi_pq[lp->id]) && state->ncontagious[i]) ||
		   ncontagious[i] != state->ncontagious[i])
		{
			epi_seir_compute(state, bf, i, lp);
			pq_clean = 1;
		}
	}

	if(pq_clean)
		pq_cleanup(g_epi_pq[lp->id]);

	epi_location_timer(state, lp);
}