Esempio n. 1
0
void Simulator_Base::Stop_Simulator (void)
{
	Sim_Method *sim_ptr;

#ifdef BOOST_THREADS
	if (Num_Threads () > 1) {
		work_step.Exit ();
		xfer_barrier.Exit ();
		veh_barrier.Exit ();
		sim_threads.join_all ();

		if (problem_output.Output_Flag ()) {
			problem_output.End_Output ();
		}
		if (event_output.Output_Flag ()) {
			event_output.End_Output ();
		}
		if (traveler_output.Output_Flag ()) {
			traveler_output.End_Output ();
		}
		if (io_threads.size () > 0) {
			io_barrier.Exit ();
			io_threads.join_all ();
		}
	}
#endif
	for (int i=0; i < Num_Simulators (); i++) {
		sim_ptr = simulator [i];
		Add_Statistics (sim_ptr->Get_Statistics ());
	}
}
Esempio n. 2
0
PlanPrep::~PlanPrep (void)
{
	if (plan_processing != 0) {
		for (int i=0; i < Num_Threads (); i++) {
			delete plan_processing [i];
			plan_processing [i] = 0;
		}
		delete plan_processing;
	}
}
Esempio n. 3
0
Simulator_Base::~Simulator_Base (void)
{
	if (simulator != 0) {
		for (int i=0; i < Num_Simulators (); i++) {
			delete simulator [i];
			simulator [i] = 0;
		}
		delete simulator;
		simulator = 0;
	}
	int num = (Num_Threads () > Num_Simulators ()) ? Num_Simulators () : Num_Threads ();

	if (step_preps != 0) {
		for (int i=0; i < num; i++) {
			delete step_preps [i];
			step_preps [i] = 0;
		}
		delete step_preps;
		step_preps = 0;
	}
	if (boundaries != 0) {
		for (int i=0; i < num; i++) {
			delete boundaries [i];
			boundaries [i] = 0;
		}
		delete boundaries;
		boundaries = 0;
	}
	if (processors != 0) {
		for (int i=0; i < num; i++) {
			delete processors [i];
			processors [i] = 0;
		}
		delete processors;
		processors = 0;
	}
}
Esempio n. 4
0
bool Simulator_Base::Step_IO (void)
{
	if (Num_Threads () > 1) {
		return (io_barrier.Start ());
	} else {
		snapshot_output.Output_Check ();
		link_delay_output.Output_Check ();
		performance_output.Output_Check ();
		ridership_output.Output_Check ();
		turn_vol_output.Output_Check ();
		occupancy_output.Output_Check ();
#ifdef MPI_EXE
		problem_output.MPI_Processing ();
		event_output.MPI_Processing ();
		traveler_output.MPI_Processing ();
#endif
		if (Master ()) {
			return (sim_read_plans.Read_Plans ());
		} else {
			return (true);
		}
	}
}
Esempio n. 5
0
void PlanSum::Program_Control (void)
{
	String key;
	bool link_flag, report_flag;

	link_flag = report_flag = false;

	if (!Set_Control_Flag (UPDATE_FLOW_RATES) && !Set_Control_Flag (UPDATE_TRAVEL_TIMES)) {
		System_File_False (NEW_LINK_DELAY);
	}

	//---- initialize the MPI thread range ----

	MPI_Setup ();

	//---- set equivalence flags ---
	
	if (Report_Flag (LINK_GROUP) || Report_Flag (RIDER_GROUP)) {
		Link_Equiv_Flag (true);
		link_flag = true;
	}
	if (skim_flag || trip_flag) {
		Zone_Equiv_Flag (true);
		zone_flag = true;
	}
	Stop_Equiv_Flag (Report_Flag (STOP_GROUP));

	//---- create the network files ----

	Data_Service::Program_Control ();
	
	Read_Select_Keys ();
	Read_Flow_Time_Keys ();

	plan_file = (Plan_File *) System_File_Handle (PLAN);
	if (!plan_file->Part_Flag ()) Num_Threads (1);

	select_flag = System_File_Flag (SELECTION);
	new_delay_flag = System_File_Flag (NEW_LINK_DELAY);

	if (System_File_Flag (LINK_DELAY)) {
		link_flag = true;
		Link_Delay_File *file = (Link_Delay_File *) System_File_Handle (LINK_DELAY);
		turn_flag = file->Turn_Flag ();
	}
	if (new_delay_flag) {
		link_flag = true;
		Link_Delay_File *file = (Link_Delay_File *) System_File_Handle (NEW_LINK_DELAY);
		turn_flag = file->Turn_Flag ();
	} else {
		turn_flag = System_File_Flag (CONNECTION);
	}
	Print (2, String ("%s Control Keys:") % Program ());

	//---- new trip time file ----

	key = Get_Control_String (NEW_TRIP_TIME_FILE);

	if (!key.empty ()) {
		time_file.File_Type ("New Trip Time File");
		time_file.File_ID ("Time");

		if (Master ()) {
			time_file.Create (Project_Filename (key));
		}
		time_flag = true;
	}

	//---- new link volume file ----

	key = Get_Control_String (NEW_LINK_VOLUME_FILE);

	if (!key.empty ()) {
		volume_file.File_Type ("New Link Volume File");
		volume_file.File_ID ("Volume");

		if (Master ()) {
			volume_file.Create (Project_Filename (key));

			volume_file.Num_Decimals (1);
			volume_file.Data_Units (Performance_Units_Map (FLOW_DATA));
			volume_file.Copy_Periods (sum_periods);

			volume_file.Create_Fields ();
			volume_file.Write_Header ();
		}
		volume_flag = new_delay_flag = link_flag = true;
	}

	//---- read report types ----

	List_Reports ();

	if (Report_Flag (TOP_100) || Report_Flag (VC_RATIO) || Report_Flag (LINK_GROUP)) {
		new_delay_flag = link_flag = report_flag = true;
		cap_factor = (double) sum_periods.Range_Length () / (Dtime (1, HOURS) * sum_periods.Num_Periods ());
	}
	if (link_flag && (!System_File_Flag (LINK) || !System_File_Flag (NODE))) {
		Error ("Link and Node Files are Required for Link-Based Output");
	}
	if (System_File_Flag (LANE_USE) && !System_File_Flag (LINK)) {
		Error ("A Link File is Required for Lane-Use Processing");
	}
	travel_flag = Report_Flag (SUM_TRAVEL);

	//---- ridership summary ----

	passenger_flag = Report_Flag (SUM_PASSENGERS);
	transfer_flag = (Report_Flag (SUM_STOPS) || Report_Flag (STOP_GROUP));
	rider_flag = (System_File_Flag (NEW_RIDERSHIP) || Report_Flag (SUM_RIDERS) || Report_Flag (RIDER_GROUP));
	xfer_flag = Report_Flag (SUM_TRANSFERS);
	xfer_detail = Report_Flag (XFER_DETAILS);

	if (passenger_flag || transfer_flag || rider_flag || xfer_flag || xfer_detail) {
		if (!System_File_Flag (TRANSIT_STOP) || !System_File_Flag (TRANSIT_ROUTE) ||
			!System_File_Flag (TRANSIT_SCHEDULE)) {

			Error ("Transit Network Files are Required for Ridership Output");
		}
		if ((passenger_flag || rider_flag) && !System_File_Flag (TRANSIT_DRIVER)) {
			Error ("A Transit Driver File is needed for Passengers Summaries");
		}
	} else {
		System_File_False (TRANSIT_STOP);
		System_File_False (TRANSIT_ROUTE);
		System_File_False (TRANSIT_SCHEDULE);
		System_File_False (TRANSIT_DRIVER);
	}

	//---- process support data ----

	if (Link_Equiv_Flag ()) {
		link_equiv.Read (Report_Flag (LINK_EQUIV));
	}
	if (Zone_Equiv_Flag ()) {
		zone_equiv.Read (Report_Flag (ZONE_EQUIV));
	}
	if (Stop_Equiv_Flag ()) {
		stop_equiv.Read (Report_Flag (STOP_EQUIV));
	}

	//---- allocate work space ----

	if (time_flag || Report_Flag (TRIP_TIME)) {
		time_flag = true;

		int periods = sum_periods.Num_Periods ();
		
		start_time.assign (periods, 0);
		mid_time.assign (periods, 0);
		end_time.assign (periods, 0);
	}

	//---- transfer arrays ----

	if (xfer_flag || xfer_detail) {
		Integers rail;

		rail.assign (10, 0);
		total_on_array.assign (10, rail);

		if (xfer_detail) {
			int num = sum_periods.Num_Periods ();
			if (num < 1) num = 1;

			walk_on_array.assign (num, total_on_array);
			drive_on_array.assign (num, total_on_array);
		}
	}

	//---- initialize the trip summary data ----

	if (travel_flag) {
		trip_sum_data.Copy_Periods (sum_periods);
	}

	//---- initialize the passenger summary data ----

	if (passenger_flag) {
		pass_sum_data.Copy_Periods (sum_periods);
	}
}
Esempio n. 6
0
bool Simulator_Service::Output_Step (Travel_Step &step)
{
	bool new_plan, problem_flag, no_veh_flag;

	Sim_Plan_Ptr sim_plan_ptr;
	Sim_Dir_Ptr sim_dir_ptr;
	Sim_Veh_Data sim_veh;
	Sim_Veh_Ptr sim_veh_ptr = 0;
	Problem_Data problem_data;
	Sim_Leg_Ptr sim_leg_ptr;

	//---- check the traveler data ----

	if (step.sim_travel_ptr == 0) {
		if (step.Traveler () < 2) return (false);

		step.sim_travel_ptr = &sim->sim_travel_array [step.Traveler ()];
	}

	//---- mark the traveler as processed in this time step ----

	step.sim_travel_ptr->Step_Code (sim->Step_Code ());

	if (step.sim_plan_ptr == 0) {
		step.sim_plan_ptr = step.sim_travel_ptr->Get_Plan ();
	}
	sim_plan_ptr = step.sim_plan_ptr;
#ifdef CHECK
	if (sim_plan_ptr == 0) sim->Error (String ("Simulator_Service::Output_Step: sim_plan_ptr, Household=%d, Problem=%d") % step.sim_travel_ptr->Household () % step.Problem ());
#endif

	if (step.sim_leg_ptr == 0) {
		step.sim_leg_ptr = sim_plan_ptr->Get_Leg ();
	}
	sim_leg_ptr = step.sim_leg_ptr;
	no_veh_flag = ((sim_leg_ptr == 0 && step.sim_travel_ptr->Vehicle () == 0) || 
		(sim_leg_ptr != 0 && sim_leg_ptr->Mode () != DRIVE_MODE && sim_leg_ptr->Type () != STOP_ID));

	new_plan = false;

	//---- process the problem message ----

	if (step.Problem () > 0) {
		problem_flag = (!sim->select_problems || sim->problem_range.In_Range (step.Problem ()));

		//---- check for lost problems ----

		if (step.Problem () == DEPARTURE_PROBLEM || step.Problem () == ARRIVAL_PROBLEM || step.Problem () == WAIT_PROBLEM || 
			step.Problem () == LOAD_PROBLEM || step.Problem () == PATH_PROBLEM) {

			if (step.sim_travel_ptr->Person () == 0) {
				stats.num_run_lost++;
			} else if (!no_veh_flag) {
				stats.num_veh_lost++;

				//---- check the lost vehicle event ----

				if (step.sim_travel_ptr->Vehicle () > 0) {
					step.Event_Type (VEH_LOST_EVENT);
					sim->sim_output_step.Event_Check (step);
				}
			}
			new_plan = true;
		}

		//---- count problems ----

		if (new_plan || problem_flag || sim->param.count_warnings) {
			step.sim_travel_ptr->Problem (1);
			sim->Set_Problem ((Problem_Type) step.Problem ());
		}

		//---- write selected problems -----

		if (problem_flag && sim->param.problem_flag && sim_plan_ptr != 0) {
			if ((int) step.size () > 0) {
				sim_veh = step.back ();
			} else if (!no_veh_flag) {
#ifdef CHECK
				if (step.sim_travel_ptr->Vehicle () < 1) sim->Error ("Simulator_Service::Output_Step: Vehicle");
#endif
				sim_veh = sim->sim_veh_array [step.sim_travel_ptr->Vehicle ()];
			}
			problem_data.Household (step.sim_travel_ptr->Household ());
			problem_data.Person (step.sim_travel_ptr->Person ());
			problem_data.Tour (sim_plan_ptr->Tour ());
			problem_data.Trip (sim_plan_ptr->Trip ());

			problem_data.Start (sim_plan_ptr->Start ());
			problem_data.End (sim_plan_ptr->End ());
			problem_data.Duration (sim_plan_ptr->Activity ());

			problem_data.Origin (sim_plan_ptr->Origin ());
			problem_data.Destination (sim_plan_ptr->Destination ());

			problem_data.Purpose (sim_plan_ptr->Purpose ());
			problem_data.Mode (sim_plan_ptr->Mode ());
			problem_data.Constraint (sim_plan_ptr->Constraint ());
			problem_data.Priority (sim_plan_ptr->Priority ());
			problem_data.Vehicle (sim_plan_ptr->Vehicle ());

			problem_data.Type (sim_plan_ptr->Type ());
			problem_data.Problem (step.Problem ());
			problem_data.Time (sim->time_step);

			problem_data.Dir_Index (sim_veh.link);
			problem_data.Lane (sim_veh.lane);
		
			if (sim_veh.link >= 0) {
				sim_dir_ptr = &sim->sim_dir_array [sim_veh.link];
				if (sim_veh.offset > sim_dir_ptr->Length ()) sim_veh.offset = sim_dir_ptr->Length ();
			}
			problem_data.Offset (sim_veh.offset);
			problem_data.Route (-1);

			if (step.sim_travel_ptr->Person () == 0) {
				int route = sim->line_array.Route (step.sim_travel_ptr->Household ());

				Int_Map_Itr map_itr = sim->line_map.find (route);
				if (map_itr != sim->line_map.end ()) {
					problem_data.Route (map_itr->second);
				}
			} else if (no_veh_flag && sim_leg_ptr != 0 && sim_leg_ptr->Type () == ROUTE_ID) {
				Int_Map_Itr map_itr = sim->line_map.find (sim_leg_ptr->Index ());
				if (map_itr != sim->line_map.end ()) {
					problem_data.Route (map_itr->second);
				}
			}
			sim->sim_output_step.Output_Problem (problem_data);
		}
	}
	step.Problem (0);

	//---- process vehicle movement ----

	if (step.size () > 0 && !no_veh_flag) {
		sim->sim_output_step.Output_Check (step);
	}
	if (sim_plan_ptr->First_Leg () < 0) {
		new_plan = true;
	}

	//---- check the vehicle data ----

	if (!no_veh_flag) {
		if (step.sim_veh_ptr == 0) {
#ifdef CHECK
			if (step.sim_travel_ptr->Vehicle () < 1) sim->Error (String ("Simulator_Service::Output_Step: Vehicle %d, Household=%d") % step.sim_travel_ptr->Vehicle () % step.sim_travel_ptr->Household ());
#endif
			step.sim_veh_ptr = &sim->sim_veh_array [step.sim_travel_ptr->Vehicle ()];
#ifdef CHECK
		} else {
			sim_veh_ptr = &sim->sim_veh_array [step.sim_travel_ptr->Vehicle ()];

			if (sim_veh_ptr != step.sim_veh_ptr) {
				sim->Error ("Simulator_Service::Output_Step: Vehicle Pointer");
			}
#endif
		}
		sim_veh_ptr = step.sim_veh_ptr;
#ifdef CHECK
		if (sim_veh_ptr == 0) sim->Error ("Simulator_Service::Output_Step: sim_veh_ptr");
#endif

		//---- park the vehicle ----

		if (new_plan || sim_veh_ptr->Parked ()) {
			step.veh_type_ptr = &sim->veh_type_array [sim_plan_ptr->Veh_Type ()];
			Remove_Vehicle (step);
		}

#ifdef THREADS

		if (Num_Threads () > 0 && (int) step.size () > 1) {
			int index = step.Dir_Index ();
			Sim_Veh_Itr sim_veh_itr;
#ifdef CHECK
			if (index < 0 || index > (int) sim->sim_dir_array.size ()) sim->Error (String ("Output_Step::Unlock Index=%d vs %d") % index % sim->sim_dir_array.size ());
#endif
			//---- release link locks ----

			for (sim_veh_itr = step.begin (); sim_veh_itr != step.end (); sim_veh_itr++) {
				if (sim_veh_itr->link != index && sim_veh_itr->link >= 0 && sim_veh_itr->lane > -1) {
					index = sim_veh_itr->link;
#ifdef CHECK
					if (index < 0 || index > (int) sim->sim_dir_array.size ()) sim->Error (String ("Output_Step::Unlock Index=%d vs %d") % index % sim->sim_dir_array.size ());
#endif
					sim_dir_ptr = &sim->sim_dir_array [index];
#ifdef CHECK
					if (step.Process_ID () > 0 && sim_dir_ptr->Lock () != step.Process_ID ()) sim->Error (String ("Output_Step::Unlock (% vs %d), Index=%d, dir=%d") % sim_dir_ptr->Lock () % step.Process_ID () % index % sim_dir_ptr->Dir ());
#endif
					sim->sim_dir_array.UnLock (sim_dir_ptr, step.Process_ID ());
				}
			}
		}
#endif
	}

	//---- move to the next plan ----

	if (new_plan) {
		if (!no_veh_flag) sim_veh_ptr->Parked (true);


		step.sim_travel_ptr->Vehicle (0);
		step.sim_travel_ptr->Next_Load (-1);

		if (step.sim_travel_ptr->Person () > 0) {
			step.sim_travel_ptr->Status (NOT_ACTIVE);
			step.sim_travel_ptr->Next_Event (sim->time_step + sim_plan_ptr->Activity ());
		} else {
			step.sim_travel_ptr->Status (OFF_NET_END);
			step.sim_travel_ptr->Next_Event (sim->param.end_time_step);
		}
		if (!step.sim_travel_ptr->Next_Plan ()) return (false);

		step.sim_plan_ptr = step.sim_travel_ptr->Get_Plan ();
		
		if (step.sim_plan_ptr->Start () > step.sim_travel_ptr->Next_Event ()) {
			step.sim_travel_ptr->Next_Event (step.sim_plan_ptr->Start ());
		}
		return (true);
	}
	if (no_veh_flag) {
		step.sim_travel_ptr->Status (OFF_NET_MOVE);
		return (true);
	} else {
		if (sim_veh_ptr->Parked ()) {
			step.sim_travel_ptr->Status (OFF_NET_MOVE);
		} else if (step.sim_travel_ptr->Status () == ON_OFF_DRIVE) {
			step.sim_travel_ptr->Status (OFF_NET_DRIVE);
		}
		return (!sim_veh_ptr->Parked ());
	}
}
Esempio n. 7
0
bool Simulator_Base::Start_Step (void)
{
	int i;
	bool status;
	Num_Vehicles (0);

	memset (veh_status, '\0', vehicle_array.size ());

	//---- update network, add/transfer travelers, process vehicles after partition boundaries ----

	if (Num_Threads () > 1) {
		status = work_step.Start ();
	} else {
		for (i=0, status = false; i < Num_Simulators (); i++) {
			if (simulator [i]->Step_Prep (work_step.Get (i))) status = true;
		}
	}
	if (status) {

		//---- process vehicles approaching partition boundaries ----

		if (Num_Threads () > 1) {
			xfer_barrier.Start ();
		} else {
			for (i=0; i < Num_Simulators (); i++) {
				simulator [i]->Boundary ();
			}
		}

		//---- process everyone else ----

		if (Num_Threads () > 1) {
			veh_barrier.Start ();
		} else {
			for (i=0; i < Num_Simulators (); i++) {
				simulator [i]->Process_Step ();
			}
		}

		int traveler, part, num;
		Int2s_Itr transfer_itr;
		Int2_Itr xfer_itr;

		for (num=0, transfer_itr = transfers.begin (); transfer_itr != transfers.end (); transfer_itr++, num++) {
			for (xfer_itr = transfer_itr->begin (); xfer_itr != transfer_itr->end (); xfer_itr++) {
				traveler = xfer_itr->first;
				part = xfer_itr->second;
				if (part >= First_Part () && part <= Last_Part ()) {
					work_step.Put (traveler, (part - First_Part ()));
#ifdef MPI_EXE
				} else {
					mpi_parts [part].push_back (xfer_itr->first);
#endif
				}
			}
		}
		for (i=0; i < Num_Simulators (); i++) {
			Add_Vehicles (simulator [i]->Num_Vehicles ());
		}
	}
	return (status);
}
Esempio n. 8
0
bool Simulator_Base::Start_Simulator (void)
{
	int num;
	Int2_Map_Itr part_itr;
	Int2_Map_Data part_rec;
	Int2_Array int2_array;

	//---- read the first travel plan ----

	if (Master ()) {
		if (!sim_read_plans.First_Plan ()) return (false);
	}

	//---- create simulators ----

	num = Last_Part () - First_Part () + 1;
	Num_Simulators (num);

	simulator = new Sim_Method * [num];

	if (Num_Parts () > 1) {
		for (part_itr = part_map.begin (); part_itr != part_map.end (); part_itr++) {
			if (part_itr->second >= First_Part () && part_itr->second <= Last_Part ()) {
				part_rec = *part_itr;
				num = part_itr->second - First_Part ();
				simulator [num] = new Sim_Method (*this, &part_rec);
			}
		}
	} else {
		*simulator = new Sim_Method (*this);
	}

	//---- create the partition lists ----

	work_step.Num_Workers (Num_Simulators ());
	transfers.assign (Num_Simulators (), int2_array);

	if (Num_Threads () == 1) {
		work_step.Num_Barriers (0);
		xfer_barrier.Num_Barriers (0);
		veh_barrier.Num_Barriers (0);
	} else {
		xfer_barrier.Num_Barriers (Num_Simulators ());
		veh_barrier.Num_Barriers (Num_Simulators ());
	}

	//---- create output threads ----

 #ifdef BOOST_THREADS
	if (Num_Threads () > 1) {
		int num_barrier = (int) snapshot_output.Output_Flag () + (int) link_delay_output.Output_Flag () + 
			(int) performance_output.Output_Flag () + (int) ridership_output.Output_Flag () + 
			(int) turn_vol_output.Output_Flag () + (int) occupancy_output.Output_Flag ();

		if (Master ()) {
			num_barrier++;
		}
#ifdef MPI_EXE
		if (problem_output.Output_Flag ()) num_barrier++;
		if (event_output.Output_Flag ()) num_barrier++;
		if (traveler_output.Output_Flag ()) num_barrier++;
#endif
		io_barrier.Num_Barriers (num_barrier);

		if (Master ()) {
			io_threads.create_thread (boost::ref (sim_read_plans));
		}
		if (snapshot_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (snapshot_output));
		}
		if (link_delay_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (link_delay_output));
		}
		if (performance_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (performance_output));
		}
		if (ridership_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (ridership_output));
		}
		if (turn_vol_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (turn_vol_output));
		}
		if (occupancy_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (occupancy_output));
		}

		//---- not barrier controlled unless MPI ----

		if (problem_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (problem_output));
		}
		if (event_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (event_output));
		}
		if (traveler_output.Output_Flag ()) {
			io_threads.create_thread (boost::ref (traveler_output));
		}
	}
#endif

	//---- processing threads ---

	num = (Num_Threads () > Num_Simulators ()) ? Num_Simulators () : Num_Threads ();

	step_preps = new Step_Preps * [num];
	boundaries = new Boundaries * [num];
	processors = new Processors * [num];

	for (int i=0; i < num; i++) {
		step_preps [i] = new Step_Preps (this);
		boundaries [i] = new Boundaries (this);
		processors [i] = new Processors (this);

#ifdef BOOST_THREADS
		if (Num_Threads () > 1) {
			sim_threads.create_thread (boost::ref (*step_preps [i]));
			sim_threads.create_thread (boost::ref (*boundaries [i]));
			sim_threads.create_thread (boost::ref (*processors [i]));
		}
#endif
	}
	return (true);
}
Esempio n. 9
0
void PathSkim::Flow_Skims (void)
{
	int mode, period, periods;
	size_t paths;
	Dtime low, high;

	One_To_Many *skim_ptr;
	Many_Data many_data;
	Many_Itr many_itr;

	Location_Itr loc_itr;
	Int_Itr org_itr, des_itr;
	
	Skim_Processor skim_processor;

	periods = route_periods.Num_Periods ();
	paths = org_loc.size () * des_loc.size () * periods;

	Break_Check (4);
	Print (1);
	Write (1, "Number of Selected Origin Locations = ") << org_loc.size ();
	Write (1, "Number of Selected Destinations     = ") << des_loc.size ();
	Write (1, "Number of Specified Time Periods    = ") << periods;
	Write (1, "Number of Potential Path Traces     = ") << paths;

	Show_Message (2, "Tracing Specified Paths -- Record");
	Set_Progress ();

	if (mode_flag) {
		mode = new_mode;
	} else {
		mode = DRIVE_MODE;
	}

	//---- initialize the skim processor ----

	skim_processor.Initialize (this, Num_Threads ());

	skim_processor.Start_Processing ();

	//---- loop through each time increment ----

	for (period = 0; period < periods; period++) {
		if (!route_periods.Period_Range (period, low, high)) continue;

		if (forward_flag) {

			//---- loop through each origin location ----

			for (org_itr = org_loc.begin (); org_itr != org_loc.end (); org_itr++) {
				skim_ptr = new One_To_Many ();

				skim_ptr->Location (*org_itr);
				skim_ptr->Time (low);
				skim_ptr->Mode (mode);
				skim_ptr->Use (use_type);
				skim_ptr->Veh_Type (veh_type);
				skim_ptr->Type (traveler_type);
				skim_ptr->Direction (constraint);

				//---- loop through each destination location ----

				for (des_itr = des_loc.begin (); des_itr != des_loc.end (); des_itr++) {
					if (*org_itr == *des_itr) continue;
					Show_Progress ();

					many_data.Clear ();
					many_data.Location (*des_itr);

					skim_ptr->push_back (many_data);
				}
				if (skim_ptr->size () > 0) {
					skim_processor.Skim_Build (skim_ptr);
				} else {
					delete skim_ptr;
				}
			}

		} else {

			//---- loop through each destination location ----

			for (des_itr = des_loc.begin (); des_itr != des_loc.end (); des_itr++) {
				skim_ptr = new One_To_Many ();

				skim_ptr->Location (*des_itr);
				skim_ptr->Time (high);
				skim_ptr->Mode (mode);
				skim_ptr->Use (use_type);
				skim_ptr->Veh_Type (veh_type);
				skim_ptr->Type (traveler_type);
				skim_ptr->Direction (constraint);

				//---- loop through each origin location ----

				for (org_itr = org_loc.begin (); org_itr != org_loc.end (); org_itr++) {
					if (*org_itr == *des_itr) continue;
					Show_Progress ();

					many_data.Clear ();
					many_data.Location (*org_itr);

					skim_ptr->push_back (many_data);
				}
				if (skim_ptr->size () > 0) {
					skim_processor.Skim_Build (skim_ptr);
				} else {
					delete skim_ptr;
				}
			}
		}
	}
	End_Progress ();
	skim_processor.Stop_Processing ();
}