From e1ca33182f5958a97f3501e918e932dccb2ddeb8 Mon Sep 17 00:00:00 2001 From: Noel Peterson Date: Fri, 13 Nov 2015 10:35:36 -0600 Subject: [PATCH] Initial commit --- src/java/com/pb/cmap/ctramp/Household.java | 1721 +++++++++++++ src/java/com/pb/cmap/ctramp/Person.java | 1956 ++++++++++++++ src/java/com/pb/cmap/ctramp/Stop.java | 178 ++ src/java/com/pb/cmap/ctramp/Tour.java | 585 +++++ .../cmap/synpop/ARCPopulationSynthesizer.java | 90 + src/java/com/pb/cmap/synpop/Aggregator.java | 404 +++ src/java/com/pb/cmap/synpop/DerivedHHARC.java | 160 ++ .../pb/cmap/synpop/DerivedHHARCFactory.java | 43 + .../pb/cmap/synpop/MasterDataDictionary.java | 715 ++++++ .../CmapAtWorkSubtourFrequencyDMU.java | 81 + .../tourBased/CmapAutoOwnershipChoiceDMU.java | 69 + ...mapCoordinatedDailyActivityPatternDMU.java | 129 + .../cmap/tourBased/CmapCtrampApplication.java | 24 + .../cmap/tourBased/CmapCtrampDmuFactory.java | 138 + .../com/pb/cmap/tourBased/CmapDcSoaDMU.java | 195 ++ .../pb/cmap/tourBased/CmapDestChoiceDMU.java | 312 +++ .../tourBased/CmapFreeParkingChoiceDMU.java | 52 + .../tourBased/CmapHouseholdDataManager.java | 466 ++++ ...apIndividualMandatoryTourFrequencyDMU.java | 163 ++ ...ndividualNonMandatoryTourFrequencyDMU.java | 165 ++ .../tourBased/CmapJointTourFrequencyDMU.java | 170 ++ .../pb/cmap/tourBased/CmapModelStructure.java | 1285 ++++++++++ .../cmap/tourBased/CmapParkingChoiceDMU.java | 81 + .../pb/cmap/tourBased/CmapStopDCSoaDMU.java | 102 + .../cmap/tourBased/CmapStopFrequencyDMU.java | 124 + .../cmap/tourBased/CmapStopLocationDMU.java | 93 + .../pb/cmap/tourBased/CmapTazDataHandler.java | 90 + .../pb/cmap/tourBased/CmapTourBasedModel.java | 301 +++ .../CmapTourDepartureTimeAndDurationDMU.java | 383 +++ .../cmap/tourBased/CmapTourModeChoiceDMU.java | 371 +++ .../cmap/tourBased/CmapTripMatrixWriter.java | 651 +++++ .../cmap/tourBased/CmapTripModeChoiceDMU.java | 393 +++ src/java/com/pb/cmap/tvpb/MazTapTazData.java | 754 ++++++ src/java/com/pb/cmap/tvpb/TVPBDMU.java | 451 ++++ src/java/com/pb/cmap/tvpb/TapPair.java | 84 + .../cmap/tvpb/TransitVirtualPathBuilder.java | 900 +++++++ src/java/com/pb/cmap/tvpb/Trip.java | 378 +++ .../ctrampIf/AtWorkSubtourFrequencyDMU.java | 320 +++ .../ctrampIf/AutoOwnershipChoiceDMU.java | 198 ++ .../CoordinatedDailyActivityPatternDMU.java | 266 ++ .../CoordinatedDailyActivityPatternModel.java | 1349 ++++++++++ .../models/ctrampIf/CtrampDmuFactoryIf.java | 45 + src/java/com/pb/models/ctrampIf/DcSoaDMU.java | 124 + .../com/pb/models/ctrampIf/Definitions.java | 20 + .../com/pb/models/ctrampIf/DestChoiceDMU.java | 243 ++ .../pb/models/ctrampIf/DestChoiceSize.java | 1342 ++++++++++ .../models/ctrampIf/FreeParkingChoiceDMU.java | 103 + .../models/ctrampIf/HouseholdDataManager.java | 2271 +++++++++++++++++ .../ctrampIf/HouseholdDataManagerIf.java | 163 ++ .../ctrampIf/HouseholdDataManagerRmi.java | 409 +++ .../models/ctrampIf/HouseholdDataWriter.java | 1801 +++++++++++++ .../com/pb/models/ctrampIf/HouseholdIf.java | 325 +++ .../IndividualMandatoryTourFrequencyDMU.java | 192 ++ ...ndividualNonMandatoryTourFrequencyDMU.java | 555 ++++ .../ctrampIf/JointTourFrequencyDMU.java | 636 +++++ .../ctrampIf/JointTourFrequencyModel.java | 611 +++++ .../pb/models/ctrampIf/MatrixDataServer.java | 220 ++ .../models/ctrampIf/MatrixDataServerRmi.java | 70 + .../pb/models/ctrampIf/ModelStructure.java | 943 +++++++ src/java/com/pb/models/ctrampIf/MyLogit.java | 95 + .../pb/models/ctrampIf/ParkingChoiceDMU.java | 135 + src/java/com/pb/models/ctrampIf/PersonIf.java | 370 +++ src/java/com/pb/models/ctrampIf/SoaDMU.java | 9 + .../com/pb/models/ctrampIf/StopDCSoaDMU.java | 153 ++ .../models/ctrampIf/StopDestChoiceSize.java | 172 ++ .../pb/models/ctrampIf/StopFrequencyDMU.java | 390 +++ src/java/com/pb/models/ctrampIf/StopIf.java | 60 + .../pb/models/ctrampIf/StopLocationDMU.java | 244 ++ .../pb/models/ctrampIf/TazDataHandler.java | 810 ++++++ .../pb/models/ctrampIf/TazDataHandlerRmi.java | 339 +++ .../com/pb/models/ctrampIf/TazDataIf.java | 168 ++ src/java/com/pb/models/ctrampIf/TimeDMU.java | 102 + .../TourDepartureTimeAndDurationDMU.java | 826 ++++++ src/java/com/pb/models/ctrampIf/TourIf.java | 158 ++ .../pb/models/ctrampIf/TourModeChoiceDMU.java | 579 +++++ .../pb/models/ctrampIf/TravelTimeModel.java | 112 + .../models/ctrampIf/TripMatrixWriterIf.java | 10 + .../pb/models/ctrampIf/TripModeChoiceDMU.java | 402 +++ src/java/com/pb/models/ctrampIf/Util.java | 91 + src/java/com/pb/models/ctrampIf/UtilRmi.java | 161 ++ .../ctrampIf/jppf/AutoDependencyModel.java | 163 ++ .../ctrampIf/jppf/ControlFileReader.java | 626 +++++ .../ctrampIf/jppf/CtrampApplication.java | 1843 +++++++++++++ .../ctrampIf/jppf/DestChoiceModelManager.java | 214 ++ .../DestinationSampleOfAlternativesModel.java | 408 +++ ...AtWorkSubtourDepartureAndDurationTime.java | 637 +++++ .../HouseholdAtWorkSubtourFrequencyModel.java | 328 +++ .../jppf/HouseholdAutoOwnershipModel.java | 541 ++++ .../jppf/HouseholdChoiceModelRunner.java | 247 ++ .../ctrampIf/jppf/HouseholdChoiceModels.java | 642 +++++ .../jppf/HouseholdChoiceModelsManager.java | 177 ++ .../jppf/HouseholdChoiceModelsTaskJppf.java | 172 ++ ...dCoordinatedDailyActivityPatternModel.java | 1049 ++++++++ .../jppf/HouseholdFreeParkingModel.java | 101 + .../HouseholdIndNonManDestChoiceModel.java | 452 ++++ ...MandatoryTourDepartureAndDurationTime.java | 1373 ++++++++++ ...IndividualMandatoryTourFrequencyModel.java | 428 ++++ ...ividualNonMandatoryTourFrequencyModel.java | 714 ++++++ .../jppf/HouseholdJointDestChoiceModel.java | 456 ++++ .../jppf/HouseholdSubTourDestChoiceModel.java | 470 ++++ .../models/ctrampIf/jppf/JointTourModels.java | 808 ++++++ .../ctrampIf/jppf/LocationChoiceTaskJppf.java | 236 ++ .../jppf/MandatoryDestChoiceModel.java | 627 +++++ .../models/ctrampIf/jppf/ModeChoiceModel.java | 614 +++++ ...MandatoryTourDepartureAndDurationTime.java | 975 +++++++ .../ctrampIf/jppf/SampleOfAlternatives.java | 191 ++ .../jppf/StopDepartArrivePeriodModel.java | 127 + ...pDestinationSampleOfAlternativesModel.java | 308 +++ .../ctrampIf/jppf/StopFrequencyModel.java | 692 +++++ .../jppf/StopLocationModeChoiceModel.java | 1473 +++++++++++ .../UsualWorkSchoolLocationChoiceModel.java | 547 ++++ .../ctrampIf/sqlite/ConnectionHelper.java | 46 + .../models/ctrampIf/sqlite/DAOException.java | 22 + .../models/ctrampIf/sqlite/SqliteService.java | 103 + 114 files changed, 49659 insertions(+) create mode 100644 src/java/com/pb/cmap/ctramp/Household.java create mode 100644 src/java/com/pb/cmap/ctramp/Person.java create mode 100644 src/java/com/pb/cmap/ctramp/Stop.java create mode 100644 src/java/com/pb/cmap/ctramp/Tour.java create mode 100644 src/java/com/pb/cmap/synpop/ARCPopulationSynthesizer.java create mode 100644 src/java/com/pb/cmap/synpop/Aggregator.java create mode 100644 src/java/com/pb/cmap/synpop/DerivedHHARC.java create mode 100644 src/java/com/pb/cmap/synpop/DerivedHHARCFactory.java create mode 100644 src/java/com/pb/cmap/synpop/MasterDataDictionary.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapAtWorkSubtourFrequencyDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapAutoOwnershipChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapCoordinatedDailyActivityPatternDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapCtrampApplication.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapCtrampDmuFactory.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapDcSoaDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapDestChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapFreeParkingChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapHouseholdDataManager.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapIndividualMandatoryTourFrequencyDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapIndividualNonMandatoryTourFrequencyDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapJointTourFrequencyDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapModelStructure.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapParkingChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapStopDCSoaDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapStopFrequencyDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapStopLocationDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTazDataHandler.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTourBasedModel.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTourDepartureTimeAndDurationDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTourModeChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTripMatrixWriter.java create mode 100644 src/java/com/pb/cmap/tourBased/CmapTripModeChoiceDMU.java create mode 100644 src/java/com/pb/cmap/tvpb/MazTapTazData.java create mode 100644 src/java/com/pb/cmap/tvpb/TVPBDMU.java create mode 100644 src/java/com/pb/cmap/tvpb/TapPair.java create mode 100644 src/java/com/pb/cmap/tvpb/TransitVirtualPathBuilder.java create mode 100644 src/java/com/pb/cmap/tvpb/Trip.java create mode 100644 src/java/com/pb/models/ctrampIf/AtWorkSubtourFrequencyDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/AutoOwnershipChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/CoordinatedDailyActivityPatternDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/CoordinatedDailyActivityPatternModel.java create mode 100644 src/java/com/pb/models/ctrampIf/CtrampDmuFactoryIf.java create mode 100644 src/java/com/pb/models/ctrampIf/DcSoaDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/Definitions.java create mode 100644 src/java/com/pb/models/ctrampIf/DestChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/DestChoiceSize.java create mode 100644 src/java/com/pb/models/ctrampIf/FreeParkingChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/HouseholdDataManager.java create mode 100644 src/java/com/pb/models/ctrampIf/HouseholdDataManagerIf.java create mode 100644 src/java/com/pb/models/ctrampIf/HouseholdDataManagerRmi.java create mode 100644 src/java/com/pb/models/ctrampIf/HouseholdDataWriter.java create mode 100644 src/java/com/pb/models/ctrampIf/HouseholdIf.java create mode 100644 src/java/com/pb/models/ctrampIf/IndividualMandatoryTourFrequencyDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/IndividualNonMandatoryTourFrequencyDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/JointTourFrequencyDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/JointTourFrequencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/MatrixDataServer.java create mode 100644 src/java/com/pb/models/ctrampIf/MatrixDataServerRmi.java create mode 100644 src/java/com/pb/models/ctrampIf/ModelStructure.java create mode 100644 src/java/com/pb/models/ctrampIf/MyLogit.java create mode 100644 src/java/com/pb/models/ctrampIf/ParkingChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/PersonIf.java create mode 100644 src/java/com/pb/models/ctrampIf/SoaDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/StopDCSoaDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/StopDestChoiceSize.java create mode 100644 src/java/com/pb/models/ctrampIf/StopFrequencyDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/StopIf.java create mode 100644 src/java/com/pb/models/ctrampIf/StopLocationDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/TazDataHandler.java create mode 100644 src/java/com/pb/models/ctrampIf/TazDataHandlerRmi.java create mode 100644 src/java/com/pb/models/ctrampIf/TazDataIf.java create mode 100644 src/java/com/pb/models/ctrampIf/TimeDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/TourDepartureTimeAndDurationDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/TourIf.java create mode 100644 src/java/com/pb/models/ctrampIf/TourModeChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/TravelTimeModel.java create mode 100644 src/java/com/pb/models/ctrampIf/TripMatrixWriterIf.java create mode 100644 src/java/com/pb/models/ctrampIf/TripModeChoiceDMU.java create mode 100644 src/java/com/pb/models/ctrampIf/Util.java create mode 100644 src/java/com/pb/models/ctrampIf/UtilRmi.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/AutoDependencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/ControlFileReader.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/CtrampApplication.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/DestChoiceModelManager.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/DestinationSampleOfAlternativesModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourDepartureAndDurationTime.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourFrequencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdAutoOwnershipModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelRunner.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModels.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsManager.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsTaskJppf.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdCoordinatedDailyActivityPatternModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdFreeParkingModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdIndNonManDestChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourDepartureAndDurationTime.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourFrequencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualNonMandatoryTourFrequencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdJointDestChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/HouseholdSubTourDestChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/JointTourModels.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/LocationChoiceTaskJppf.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/MandatoryDestChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/ModeChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/NonMandatoryTourDepartureAndDurationTime.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/SampleOfAlternatives.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/StopDepartArrivePeriodModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/StopDestinationSampleOfAlternativesModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/StopFrequencyModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/StopLocationModeChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/jppf/UsualWorkSchoolLocationChoiceModel.java create mode 100644 src/java/com/pb/models/ctrampIf/sqlite/ConnectionHelper.java create mode 100644 src/java/com/pb/models/ctrampIf/sqlite/DAOException.java create mode 100644 src/java/com/pb/models/ctrampIf/sqlite/SqliteService.java diff --git a/src/java/com/pb/cmap/ctramp/Household.java b/src/java/com/pb/cmap/ctramp/Household.java new file mode 100644 index 0000000..da43be6 --- /dev/null +++ b/src/java/com/pb/cmap/ctramp/Household.java @@ -0,0 +1,1721 @@ +package com.pb.cmap.ctramp; + +import java.util.HashMap; +import java.util.Random; +import org.apache.log4j.Logger; +import com.pb.common.util.ObjectUtil; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.StopIf; +import com.pb.models.ctrampIf.TourIf; + +public class Household implements HouseholdIf, java.io.Serializable +{ + + private boolean debugChoiceModels; + + private int hhId; + private int hhIncome; + private int hhIncomeInDollars; + private int hhSize; + private int hhType; + private int unitType; + private int hhBldgsz; + private int hhWorkers; + + private int homeTaz; + private int homeWalkSubzone; + + private Person[] persons; + + private Tour[] jointTours; + + private int aoModelAutos; + private int freeParkingAvailable; + private String cdapModelPattern; + private int imtfModelPattern; + private String jtfModelPattern; + + private Random hhRandom; + private int randomCount = 0; + private HashMap uwslRandomCountList; + private int preAoRandomCount; + private int aoRandomCount; + private int fpRandomCount; + private int cdapRandomCount; + private int imtfRandomCount; + private int imtodRandomCount; + private int immcRandomCount; + private int awfRandomCount; + private int awlRandomCount; + private int awtodRandomCount; + private int awmcRandomCount; + private int jtfRandomCount; + private int jtlRandomCount; + private int jtodRandomCount; + private int jmcRandomCount; + private int inmtfRandomCount; + private int inmtlRandomCount; + private int inmtodRandomCount; + private int inmmcRandomCount; + private int stfRandomCount; + private int stlRandomCount; + + private int maxAdultOverlaps; + private int maxChildOverlaps; + private int maxAdultChildOverlaps; + + private ModelStructure modelStructure; + + public Household(ModelStructure modelStructure) + { + this.modelStructure = modelStructure; + hhRandom = new Random(); + uwslRandomCountList = new HashMap(); + } + + public Person[] getPersons() + { + return persons; + } + + public void initializeWindows() + { + + // loop through the person array (1-based) + for (int i = 1; i < persons.length; ++i) + { + persons[i].initializeWindows(); + } + + } + + public void setDebugChoiceModels(boolean value) + { + debugChoiceModels = value; + } + + public void setHhId(int id, int baseSeed) + { + hhId = id; + randomCount = 0; + hhRandom.setSeed(baseSeed + hhId); + } + + public void setRandomObject(Random r) + { + hhRandom = r; + } + + public void setHhRandomCount(int count) + { + randomCount = count; + } + + // work/school location choice uses shadow pricing, so save randomCount per + // iteration + public void setUwslRandomCount(int iter, int count) + { + uwslRandomCountList.put(iter, count); + } + + public void setPreAoRandomCount(int count) + { + preAoRandomCount = count; + } + + public void setAoRandomCount(int count) + { + aoRandomCount = count; + } + + public void setFpRandomCount(int count) + { + fpRandomCount = count; + } + + public void setCdapRandomCount(int count) + { + cdapRandomCount = count; + } + + public void setImtfRandomCount(int count) + { + imtfRandomCount = count; + } + + public void setImtodRandomCount(int count) + { + imtodRandomCount = count; + } + + public void setAwfRandomCount(int count) + { + awfRandomCount = count; + } + + public void setAwlRandomCount(int count) + { + awlRandomCount = count; + } + + public void setAwtodRandomCount(int count) + { + awtodRandomCount = count; + } + + public void setJtfRandomCount(int count) + { + jtfRandomCount = count; + } + + public void setJtlRandomCount(int count) + { + jtlRandomCount = count; + } + + public void setJtodRandomCount(int count) + { + jtodRandomCount = count; + } + + public void setInmtfRandomCount(int count) + { + inmtfRandomCount = count; + } + + public void setInmtlRandomCount(int count) + { + inmtlRandomCount = count; + } + + public void setInmtodRandomCount(int count) + { + inmtodRandomCount = count; + } + + public void setStfRandomCount(int count) + { + stfRandomCount = count; + } + + public void setStlRandomCount(int count) + { + stlRandomCount = count; + } + + public void setHhTaz(int taz) + { + homeTaz = taz; + } + + public void setHhWalkSubzone(int subzone) + { + homeWalkSubzone = subzone; + } + + public void setHhAutos(int autos) + { + // this sets the variable that will be used in work/school location choice. + // after auto ownership runs, this variable gets updated with number of autos + // for result. + aoModelAutos = autos; + } + + public void setAutoOwnershipModelResult(int aoModelAlternativeChosen) + { + // store the number of autos owned by the household (AO model alternative - + // 1). + aoModelAutos = aoModelAlternativeChosen - 1; + } + + /** + * auto sufficiency: 1 if cars < workers, 2 if cars equal workers, 3 if cars > + * workers + * + * @return auto sufficiency value + */ + public int getAutoSufficiency() + { + if (aoModelAutos < hhWorkers) return 1; + else if (aoModelAutos == hhWorkers) return 2; + else return 3; + } + + public int getAutoOwnershipModelResult() + { + return aoModelAutos; + } + + public void setFreeParkingAvailableResult(int fpResult) + { + freeParkingAvailable = fpResult; + } + + public int getFreeParkingAvailableResult() + { + return freeParkingAvailable; + } + + public void setCoordinatedDailyActivityPatternResult(String pattern) + { + cdapModelPattern = pattern; + } + + public String getCoordinatedDailyActivityPattern() + { + return cdapModelPattern; + } + + public void setJointTourFreqResult(int altIndex, String altName) + { + jtfModelPattern = String.format("%d_%s", altIndex, altName); + } + + public int getJointTourFreqChosenAlt() + { + int returnValue = 0; + if (jtfModelPattern == null) + { + returnValue = 0; + } else + { + int endIndex = jtfModelPattern.indexOf('_'); + returnValue = Integer.parseInt(jtfModelPattern.substring(0, endIndex)); + } + return returnValue; + } + + public String getJointTourFreqChosenAltName() + { + String returnValue = "none"; + if (jtfModelPattern != null) + { + int startIndex = jtfModelPattern.indexOf('_') + 1; + returnValue = jtfModelPattern.substring(startIndex); + } + return returnValue; + } + + public void setHhBldgsz(int code) + { + hhBldgsz = code; + } + + public int getHhBldgsz() + { + return hhBldgsz; + } + + public void setHhSize(int numPersons) + { + hhSize = numPersons; + persons = new Person[numPersons + 1]; + for (int i = 1; i <= numPersons; i++) + persons[i] = new Person(this, i, modelStructure); + + } + + public void setHhIncome(int category) + { + hhIncome = category; + } + + public void setHhIncomeInDollars(int dollars) + { + hhIncomeInDollars = dollars; + } + + public void setHhWorkers(int numWorkers) + { + hhWorkers = numWorkers; + } + + public void setHhType(int type) + { + hhType = type; + } + + // 0=Housing unit, 1=Institutional group quarters, 2=Noninstitutional group + // quarters + public void setUnitType(int type) + { + unitType = type; + } + + public boolean getDebugChoiceModels() + { + return debugChoiceModels; + } + + public int getHhSize() + { + return hhSize; + } + + public int getNumTotalIndivTours() + { + int count = 0; + for (int i = 1; i < persons.length; i++) + count += persons[i].getNumTotalIndivTours(); + return count; + } + + public int getNumberOfNonWorkingAdults() + { + int count = 0; + for (int i = 1; i < persons.length; i++) + count += persons[i].getPersonIsNonWorkingAdultUnder65() + + persons[i].getPersonIsNonWorkingAdultOver65(); + return count; + } + + public int getIsNonFamilyHousehold() + { + + if (hhType == HouseholdType.NON_FAMILY_MALE_ALONE.ordinal()) return (1); + if (hhType == HouseholdType.NON_FAMILY_MALE_NOT_ALONE.ordinal()) return (1); + if (hhType == HouseholdType.NON_FAMILY_FEMALE_ALONE.ordinal()) return (1); + if (hhType == HouseholdType.NON_FAMILY_FEMALE_NOT_ALONE.ordinal()) return (1); + + return (0); + } + + /** + * unitType: 0=Housing unit, 1=Institutional group quarters, 2=Noninstitutional + * group quarters + * + * @return 1 if household is group quarters, 0 for non-group quarters + */ + public int getIsGroupQuarters() + { + if (unitType == 0) return 0; + else return 1; + } + + public int getNumStudents() + { + int count = 0; + for (int i = 1; i < persons.length; ++i) + { + count += persons[i].getPersonIsStudent(); + } + return (count); + } + + public int getNumGradeSchoolStudents() + { + int count = 0; + for (int i = 1; i < persons.length; ++i) + { + count += persons[i].getPersonIsGradeSchool(); + } + return (count); + } + + public int getNumHighSchoolStudents() + { + int count = 0; + for (int i = 1; i < persons.length; ++i) + { + count += persons[i].getPersonIsHighSchool(); + } + return (count); + } + + public int getNumberOfChildrenUnder16WithHomeOrNonMandatoryActivity() { + + int count = 0; + + for (int i = 1; i < persons.length; ++i) { + if ( persons[i].getAge() < 16 && (! persons[i].getCdapActivity().equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN)) ) + count ++; + } + + return (count); + } + + public int getNumberOfChildren6To18WithoutMandatoryActivity() + { + + int count = 0; + + for (int i = 1; i < persons.length; ++i) { + count += persons[i].getPersonIsChild6To18WithoutMandatoryActivity(); + } + + return (count); + } + + public int getNumberOfPreDrivingWithNonHomeActivity() + { + + int count = 0; + for (int i = 1; i < persons.length; ++i) + { + // count only predrving kids + if (persons[i].getPersonIsStudentDriving() == 1) + { + // count only if CDAP is M or N (i.e. not H) + if (!persons[i].getCdapActivity().equalsIgnoreCase(ModelStructure.HOME_PATTERN)) + count++; + } + } + + return count; + } + + public int getNumberOfPreschoolWithNonHomeActivity() + { + + int count = 0; + for (int i = 1; i < persons.length; ++i) + { + // count only predrving kids + if (persons[i].getPersonIsPreschoolChild() == 1) + { + // count only if CDAP is M or N (i.e. not H) + if (!persons[i].getCdapActivity().equalsIgnoreCase(ModelStructure.HOME_PATTERN)) + count++; + } + } + + return count; + } + + /** + * return the number of school age students this household has for the purpose + * index. + * + * @param purposeIndex is the DC purpose index to be compared to the usual school + * location index saved for this person upon reading synthetic + * population file. + * @return num, a value of the number of school age students in the household for + * this purpose index. + */ + public int getNumberOfDrivingAgedStudentsWithDcPurposeIndex(int segmentIndex) + { + int num = 0; + for (int j = 1; j < persons.length; j++) + { + if (persons[j].getPersonIsStudentDriving() == 1 + && persons[j].getSchoolLocationPurposeIndex() == segmentIndex) num++; + } + return num; + } + + public int getNumberOfNonDrivingAgedStudentsWithDcPurposeIndex(int segmentIndex) + { + int num = 0; + for (int j = 1; j < persons.length; j++) + { + if (persons[j].getPersonIsStudentNonDriving() == 1 + || persons[j].getPersonIsPreschoolChild() == 1 + && persons[j].getSchoolLocationPurposeIndex() == segmentIndex) num++; + } + return num; + } + + public Person getPerson(int persNum) + { + if (persNum < 1 || persNum > hhSize) { throw new RuntimeException(String.format( + "persNum value = %d is out of range for hhSize = %d", persNum, hhSize)); } + + return persons[persNum]; + } + + // methods DMU will use to get info from household object + + public int getHhId() + { + return hhId; + } + + public Random getHhRandom() + { + randomCount++; + return hhRandom; + } + + public int getHhRandomCount() + { + return randomCount; + } + + public int getUwslRandomCount(int iter) + { + return uwslRandomCountList.get(iter); + } + + public int getPreAoRandomCount() + { + return preAoRandomCount; + } + + public int getAoRandomCount() + { + return aoRandomCount; + } + + public int getFpRandomCount() + { + return fpRandomCount; + } + + public int getCdapRandomCount() + { + return cdapRandomCount; + } + + public int getImtfRandomCount() + { + return imtfRandomCount; + } + + public int getImtodRandomCount() + { + return imtodRandomCount; + } + + public int getJtfRandomCount() + { + return jtfRandomCount; + } + + public int getAwfRandomCount() + { + return awfRandomCount; + } + + public int getAwlRandomCount() + { + return awlRandomCount; + } + + public int getAwtodRandomCount() + { + return awtodRandomCount; + } + + public int getJtlRandomCount() + { + return jtlRandomCount; + } + + public int getJtodRandomCount() + { + return jtodRandomCount; + } + + public int getInmtfRandomCount() + { + return inmtfRandomCount; + } + + public int getInmtlRandomCount() + { + return inmtlRandomCount; + } + + public int getInmtodRandomCount() + { + return inmtodRandomCount; + } + + public int getStfRandomCount() + { + return stfRandomCount; + } + + public int getStlRandomCount() + { + return stlRandomCount; + } + + + public int getAwmcRandomCount() { + return awmcRandomCount; + } + + public int getImmcRandomCount() { + return immcRandomCount; + } + + public int getInmmcRandomCount() { + return inmmcRandomCount; + } + + public int getJmcRandomCount() { + return jmcRandomCount; + } + + + + public int getHhTaz() + { + return homeTaz; + } + + public int getHhWalkSubzone() + { + return homeWalkSubzone; + } + + public int getIncome() + { + return hhIncome; + } + + public int getIncomeInDollars() + { + return hhIncomeInDollars; + } + + public int getIncomeSegment() + { + return modelStructure.getIncomeSegment(hhIncomeInDollars); + } + + public int getWorkers() + { + return hhWorkers; + } + + public int getDrivers() + { + return getNumPersons16plus(); + } + + public int getSize() + { + return hhSize; + } + + public int getChildunder16() + { + if (getNumChildrenUnder16() > 0) return 1; + else return 0; + } + + public int getChild16plus() + { + if (getNumPersons16plus() > 0) return 1; + else return 0; + } + + public int getNumChildrenUnder16() + { + int numChildrenUnder16 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() < 16) numChildrenUnder16++; + } + return numChildrenUnder16; + } + + public int getNumChildrenUnder19() + { + int numChildrenUnder19 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() < 19) numChildrenUnder19++; + } + return numChildrenUnder19; + } + + public int getNumChildren() + { + int numChildrenUnder18 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() < 18) numChildrenUnder18++; + } + return numChildrenUnder18; + } + + public int getNumPersons0to4() + { + int numPersons0to4 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() < 5) numPersons0to4++; + } + return numPersons0to4; + } + + public Person getOldestPerson() + { + + Person oldestPerson = persons[1]; + int maxAge = persons[1].getAge(); + + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() > maxAge) { + maxAge = persons[i].getAge(); + oldestPerson = persons[i]; + } + } + return oldestPerson; + } + + /** + * used in AO choice utility + * + * @return number of persons age 6 to 15, inclusive + */ + public int getNumPersons6to15() + { + int numPersons6to15 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 6 && persons[i].getAge() <= 15) numPersons6to15++; + } + return numPersons6to15; + } + + /** + * used in Stop Frequency choice utility + * + * @return number of persons age 5 to 15, inclusive + */ + public int getNumPersons5to15() + { + int numPersons5to15 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 5 && persons[i].getAge() <= 15) numPersons5to15++; + } + return numPersons5to15; + } + + public int getNumPersons16to17() + { + int numPersons16to17 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 16 && persons[i].getAge() <= 17) numPersons16to17++; + } + return numPersons16to17; + } + + public int getNumPersons16plus() + { + int numPersons16plus = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 16) numPersons16plus++; + } + return numPersons16plus; + } + + public int getNumPersons18plus() + { + int numPersons18plus = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 18) numPersons18plus++; + } + return numPersons18plus; + } + + public int getNumPersons80plus() + { + int numPersons80plus = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 80) numPersons80plus++; + } + return numPersons80plus; + } + + public int getNumPersons18to24() + { + int numPersons18to24 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 18 && persons[i].getAge() <= 24) numPersons18to24++; + } + return numPersons18to24; + } + + public int getNumPersons65to79() + { + int numPersons65to79 = 0; + for (int i = 1; i < persons.length; i++) + { + if (persons[i].getAge() >= 65 && persons[i].getAge() <= 79) numPersons65to79++; + } + return numPersons65to79; + } + + public int getNumFtWorkers() + { + int numFtWorkers = 0; + for (int i = 1; i < persons.length; i++) + numFtWorkers += persons[i].getPersonIsFullTimeWorker(); + return numFtWorkers; + } + + public int getNumPtWorkers() + { + int numPtWorkers = 0; + for (int i = 1; i < persons.length; i++) + numPtWorkers += persons[i].getPersonIsPartTimeWorker(); + return numPtWorkers; + } + + public int getNumUnivStudents() + { + int numUnivStudents = 0; + for (int i = 1; i < persons.length; i++) + numUnivStudents += persons[i].getPersonIsUniversityStudent(); + return numUnivStudents; + } + + public int getNumNonWorkAdults() + { + int numNonWorkAdults = 0; + for (int i = 1; i < persons.length; i++) + numNonWorkAdults += persons[i].getPersonIsNonWorkingAdultUnder65(); + return numNonWorkAdults; + } + + public int getNumAdults() + { + int numAdults = 0; + for (int i = 1; i < persons.length; i++) + numAdults += ( persons[i].getPersonIsFullTimeWorker() + + persons[i].getPersonIsPartTimeWorker() + + persons[i].getPersonIsUniversityStudent() + + persons[i].getPersonIsNonWorkingAdultUnder65() + + persons[i].getPersonIsNonWorkingAdultOver65() ); + return numAdults; + } + + public int getNumRetired() + { + int numRetired = 0; + for (int i = 1; i < persons.length; i++) + numRetired += persons[i].getPersonIsNonWorkingAdultOver65(); + return numRetired; + } + + public int getNumDrivingStudents() + { + int numDrivingStudents = 0; + for (int i = 1; i < persons.length; i++) + numDrivingStudents += persons[i].getPersonIsStudentDriving(); + return numDrivingStudents; + } + + public int getNumNonDrivingStudents() + { + int numNonDrivingStudents = 0; + for (int i = 1; i < persons.length; i++) + numNonDrivingStudents += persons[i].getPersonIsStudentNonDriving(); + return numNonDrivingStudents; + } + + public int getNumPreschool() + { + int numPreschool = 0; + for (int i = 1; i < persons.length; i++) + numPreschool += persons[i].getPersonIsPreschoolChild(); + return numPreschool; + } + + public int getNumHighSchoolGraduates() + { + int numGrads = 0; + for (int i = 1; i < persons.length; i++) + numGrads += persons[i].getPersonIsHighSchoolGraduate(); + return numGrads; + } + + public int getHighestEducationAttainment() + { + int highest = 0; + int educ = 0; + for (int i = 1; i < persons.length; i++) + educ = persons[i].getPersonEducAttainment(); + highest = (educ > highest) ? educ : highest; + return highest; + } + + /** + * joint tour frequency choice is not applied to a household unless it has: 2 or + * more persons, each with at least one out-of home activity, and at least 1 of + * the persons not a pre-schooler. + * */ + public int getValidHouseholdForJointTourFrequencyModel() + { + + // return one of the following condition codes for this household producing + // joint tours: + // 1: household eligible for joint tour production + // 2: household ineligible due to 1 person hh. + // 3: household ineligible due to fewer than 2 persons traveling out of home + // 4: household ineligible due to fewer than 1 non-preschool person traveling + // out of home + + // no joint tours for single person household + if (hhSize == 1) return 2; + + int leavesHome = 0; + int nonPreSchoolerLeavesHome = 0; + for (int i = 1; i < persons.length; i++) + { + if (!persons[i].getCdapActivity().equalsIgnoreCase("H")) + { + leavesHome++; + if (persons[i].getPersonIsPreschoolChild() == 0) nonPreSchoolerLeavesHome++; + } + } + + // if the number of persons leaving home during the day is not at least 2, no + // joint tours + if (leavesHome < 2) return 3; + + // if the number of non-preschool persons leaving home during the day is not + // at least 1, no joint tours + if (nonPreSchoolerLeavesHome < 1) return 4; + + // if all conditions are met, we can apply joint tour frequency model to this + // household + return 1; + + } + + /** + * return maximum periods of overlap between this person and other adult persons in + * the household. + * + * @return the most number of periods mutually available between this person and + * other adult household members + */ + public int getMaxAdultOverlaps() + { + return maxAdultOverlaps; + } + + /** + * return maximum periods of overlap between this person and other children in the + * household. + * + * @return the most number of periods mutually available between this person and + * other child household members + */ + public int getMaxChildOverlaps() + { + return maxChildOverlaps; + } + + /** + * return maximum periods of overlap between this person(adult/child) and other + * persons(child/adult) in the household. + * + * @return the most number of periods mutually available between this person and + * other type household members + */ + public int getMaxAdultChildOverlaps() + { + return maxAdultChildOverlaps; + } + + /** + * @return number of adults in household with "M" or "N" activity pattern - that + * is, traveling adults. + */ + public int getTravelActiveAdults() + { + + int adultsStayingHome = 0; + int adults = 0; + for (int p = 1; p < persons.length; p++) + { + // person is an adult + if (persons[p].getPersonIsAdult() == 1) + { + adults++; + if (persons[p].getCdapActivity().equalsIgnoreCase("H")) adultsStayingHome++; + } + } + + // return the number of adults traveling = number of adults minus the number + // of adults staying home. + return adults - adultsStayingHome; + + } + + /** + * @return number of children in household with "M" or "N" activity pattern - + * that is, traveling children. + */ + public int getTravelActiveChildren() + { + + int childrenStayingHome = 0; + int children = 0; + for (int p = 1; p < persons.length; p++) + { + // person is not an adult + if (persons[p].getPersonIsAdult() == 0) + { + children++; + if (persons[p].getCdapActivity().equalsIgnoreCase("H")) childrenStayingHome++; + } + } + + // return the number of adults traveling = number of adults minus the number + // of adults staying home. + return children - childrenStayingHome; + + } + + public void calculateTimeWindowOverlaps() + { + + boolean pAdult; + boolean qAdult; + + maxAdultOverlaps = 0; + maxChildOverlaps = 0; + maxAdultChildOverlaps = 0; + + int[] maxAdultOverlapsP = new int[persons.length]; + int[] maxChildOverlapsP = new int[persons.length]; + + // loop over persons in the household and count available time windows + for (int p = 1; p < persons.length; p++) + { + + // determine if person p is an adult -- that is, person is not any of the + // three child types + pAdult = persons[p].getPersonIsPreschoolChild() == 0 + && persons[p].getPersonIsStudentNonDriving() == 0 + && persons[p].getPersonIsStudentDriving() == 0; + + + // loop over person indices to compute length of pairwise available time windows. + for (int q = 1; q < persons.length; q++) + { + + if (p == q) continue; + + // determine if person q is an adult -- that is, person is not any of the three child types + qAdult = persons[q].getPersonIsPreschoolChild() == 0 + && persons[q].getPersonIsStudentNonDriving() == 0 + && persons[q].getPersonIsStudentDriving() == 0; + + // get the length of the maximum pairwise available time window between persons p and q. + int maxWindow = persons[p].getMaximumContinuousPairwiseAvailableWindow( persons[q].getTimeWindows() ); + + // determine max time window overlap between adult pairs, children pairs, and mixed pairs in the household + // for max windows in all pairs in hh, don't need to check q,p once we'alread done p,q, so skip q <= p. + if ( q > p ){ + if (pAdult && qAdult) { + if (maxWindow > maxAdultOverlaps) + maxAdultOverlaps = maxWindow; + } + else if (!pAdult && !qAdult) { + if (maxWindow > maxChildOverlaps) + maxChildOverlaps = maxWindow; + } + else { + if (maxWindow > maxAdultChildOverlaps) + maxAdultChildOverlaps = maxWindow; + } + } + + + // determine the max time window overlap between this person and other household adults and children. + if ( qAdult) { + if (maxWindow > maxAdultOverlapsP[p]) + maxAdultOverlapsP[p] = maxWindow; + } + else { + if (maxWindow > maxChildOverlapsP[p]) + maxChildOverlapsP[p] = maxWindow; + } + + } // end of person q + + // set person attributes + persons[p].setMaxAdultOverlaps(maxAdultOverlapsP[p]); + persons[p].setMaxChildOverlaps(maxChildOverlapsP[p]); + + } // end of person p + + } + + public boolean[] getAvailableJointTourTimeWindows(TourIf t, int[] altStarts, int[] altEnds) + { + byte[] participatingPersonIndices = t.getPersonNumArray(); + + // availability array for each person + boolean[][] availability = new boolean[participatingPersonIndices.length][]; + + for (int i = 0; i < participatingPersonIndices.length; i++) + { + + int personNum = participatingPersonIndices[i]; + Person person = persons[personNum]; + + // availability array is 1-based indexing + availability[i] = new boolean[altStarts.length + 1]; + + for (int k = 1; k <= altStarts.length; k++) + { + int start = altStarts[k - 1]; + int end = altEnds[k - 1]; + availability[i][k] = person.isWindowAvailable(start, end); + } + + } + + boolean[] jointAvailability = new boolean[availability[0].length]; + + for (int k = 0; k < jointAvailability.length; k++) + { + jointAvailability[k] = true; + for (int i = 0; i < participatingPersonIndices.length; i++) + { + if (!availability[i][k]) + { + jointAvailability[k] = false; + break; + } + } + } + + return jointAvailability; + + } + + public int getMaxJointTimeWindow( TourIf t ) + { + // get array of person array indices participating in joint tour + byte[] participatingPersonIndices = t.getPersonNumArray(); + + // create an array to hold time window arrays for each participant + byte[][] personWindows = new byte[participatingPersonIndices.length][]; + + // get time window arrays for each participant + int k = 0; + for (int i : participatingPersonIndices ) + personWindows[k++] = persons[i].getTimeWindows(); + + int count = 0;; + int maxCount = 0; + // loop over time window intervals + for (int w=1; w < personWindows[0].length; w++) { + + // loop over party; determine if interval is available for everyone in party; + boolean available = true; + for (k=0; k < personWindows.length; k++) { + if ( personWindows[k][w] > 0 ) { + available = false; + break; + } + } + + // if available for whole party, increment count; determine maximum continous time window available to whole party. + if ( available ) { + count++; + if ( count > maxCount ) + maxCount = count; + } + else { + count = 0; + } + + } + + return maxCount; + } + + public void scheduleJointTourTimeWindows(TourIf t, int start, int end) + { + byte[] participatingPersonIndices = t.getPersonNumArray(); + for (int i : participatingPersonIndices ) + { + Person person = persons[i]; + person.scheduleWindow(start, end); + } + } + + public void createJointTourArray() + { + jointTours = new Tour[0]; + } + + // this constructor used for joint tour creation for household with 1 joint tour + public void createJointTourArray(Object[] t1Data) + { + int primaryPurposeIndex = modelStructure.getPrimaryPurposeIndex( modelStructure.getPrimaryPurposeString((String)t1Data[1]) ); + Tour t1 = new Tour( this, (String) t1Data[1], ModelStructure.JOINT_NON_MANDATORY_CATEGORY, primaryPurposeIndex ); + + jointTours = new Tour[1]; + t1.setTourOrigTaz(homeTaz); + t1.setTourDestTaz(0); + jointTours[0] = t1; + } + + // this constructor used for joint tours creation for household with 2 joint tours + public void createJointTourArray(Object[] t1Data, Object[] t2Data) + { + int primaryPurposeIndex = modelStructure.getPrimaryPurposeIndex( modelStructure.getPrimaryPurposeString((String)t1Data[1]) ); + Tour t1 = new Tour( this, (String) t1Data[1], ModelStructure.JOINT_NON_MANDATORY_CATEGORY, primaryPurposeIndex ); + + primaryPurposeIndex = modelStructure.getPrimaryPurposeIndex( modelStructure.getPrimaryPurposeString((String)t2Data[1]) ); + Tour t2 = new Tour( this, (String) t2Data[1], ModelStructure.JOINT_NON_MANDATORY_CATEGORY, primaryPurposeIndex ); + + jointTours = new Tour[2]; + t1.setTourOrigTaz(homeTaz); + t1.setTourDestTaz(0); + t1.setTourId(0); + t2.setTourOrigTaz(homeTaz); + t2.setTourDestTaz(0); + t2.setTourId(1); + jointTours[0] = t1; + jointTours[1] = t2; + } + + public Tour[] getJointTourArray() + { + return jointTours; + } + + public void initializeForAoRestart() + { + jointTours = null; + + aoModelAutos = 0; + freeParkingAvailable = 0; + cdapModelPattern = null; + imtfModelPattern = 0; + jtfModelPattern = null; + + fpRandomCount = 0; + cdapRandomCount = 0; + imtfRandomCount = 0; + imtodRandomCount = 0; + immcRandomCount = 0; + awfRandomCount = 0; + awlRandomCount = 0; + awtodRandomCount = 0; + awmcRandomCount = 0; + jtfRandomCount = 0; + jtlRandomCount = 0; + jtodRandomCount = 0; + jmcRandomCount = 0; + inmtfRandomCount = 0; + inmtlRandomCount = 0; + inmtodRandomCount = 0; + inmmcRandomCount = 0; + stfRandomCount = 0; + stlRandomCount = 0; + + maxAdultOverlaps = 0; + maxChildOverlaps = 0; + maxAdultChildOverlaps = 0; + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForAoRestart(); + + } + + public void initializeForImtfRestart() + { + jointTours = null; + + imtfModelPattern = 0; + jtfModelPattern = null; + + imtodRandomCount = 0; + immcRandomCount = 0; + jtfRandomCount = 0; + jtlRandomCount = 0; + jtodRandomCount = 0; + jmcRandomCount = 0; + inmtfRandomCount = 0; + inmtlRandomCount = 0; + inmtodRandomCount = 0; + inmmcRandomCount = 0; + awfRandomCount = 0; + awlRandomCount = 0; + awtodRandomCount = 0; + awmcRandomCount = 0; + stfRandomCount = 0; + stlRandomCount = 0; + + maxAdultOverlaps = 0; + maxChildOverlaps = 0; + maxAdultChildOverlaps = 0; + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForImtfRestart(); + + } + + public void initializeForJtfRestart() + { + + jtfModelPattern = null; + + jtfRandomCount = 0; + jtlRandomCount = 0; + jtodRandomCount = 0; + jmcRandomCount = 0; + inmtfRandomCount = 0; + inmtlRandomCount = 0; + inmtodRandomCount = 0; + inmmcRandomCount = 0; + awfRandomCount = 0; + awlRandomCount = 0; + awtodRandomCount = 0; + awmcRandomCount = 0; + stfRandomCount = 0; + stlRandomCount = 0; + + initializeWindows(); + + if (jointTours != null) + { + for (Tour t : jointTours) + { + t.clearStopModelResults(); + } + } + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForJtfRestart(); + + jointTours = null; + + } + + public void initializeForInmtfRestart() + { + + inmtfRandomCount = 0; + inmtlRandomCount = 0; + inmtodRandomCount = 0; + inmmcRandomCount = 0; + awfRandomCount = 0; + awlRandomCount = 0; + awtodRandomCount = 0; + awmcRandomCount = 0; + stfRandomCount = 0; + stlRandomCount = 0; + + initializeWindows(); + + if (jointTours != null) + { + for (Tour t : jointTours) + { + for (int i : t.getPersonNumArray()) + persons[i].scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + } + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForInmtfRestart(); + + } + + public void initializeForAwfRestart() + { + + awfRandomCount = 0; + awlRandomCount = 0; + awtodRandomCount = 0; + awmcRandomCount = 0; + stfRandomCount = 0; + stlRandomCount = 0; + + initializeWindows(); + + if (jointTours != null) + { + for (Tour t : jointTours) + { + for (int i : t.getPersonNumArray()) + persons[i].scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + } + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForAwfRestart(); + + } + + public void initializeForStfRestart() + { + + stfRandomCount = 0; + stlRandomCount = 0; + + for (int i = 1; i < persons.length; i++) + persons[i].initializeForStfRestart(); + + } + + public void logHouseholdObject(String titleString, Logger logger) + { + + int totalChars = 72; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "H"; + + logger.info(separater); + logger.info(titleString); + logger.info(separater); + + Household.logHelper(logger, "hhId: ", hhId, totalChars); + Household.logHelper(logger, "debugChoiceModels: ", debugChoiceModels ? "True" : "False", + totalChars); + Household.logHelper(logger, "hhIncome: ", hhIncome, totalChars); + Household.logHelper(logger, "hhIncomeInDollars: ", hhIncomeInDollars, totalChars); + Household.logHelper(logger, "hhSize: ", hhSize, totalChars); + Household.logHelper(logger, "hhType: ", hhType, totalChars); + Household.logHelper(logger, "hhWorkers: ", hhWorkers, totalChars); + Household.logHelper(logger, "homeTaz: ", homeTaz, totalChars); + Household.logHelper(logger, "homeWalkSubzone: ", homeWalkSubzone, totalChars); + Household.logHelper(logger, "aoModelAutos: ", aoModelAutos, totalChars); + Household.logHelper(logger, "freeParkingAvailable: ", freeParkingAvailable, totalChars); + Household.logHelper(logger, "cdapModelPattern: ", cdapModelPattern, totalChars); + Household.logHelper(logger, "imtfModelPattern: ", imtfModelPattern, totalChars); + Household.logHelper(logger, "jtfModelPattern: ", jtfModelPattern, totalChars); + Household.logHelper(logger, "randomCount: ", randomCount, totalChars); + if (uwslRandomCountList.size() > 0) + { + for (int i : uwslRandomCountList.keySet()) + Household.logHelper(logger, String.format("uwslRandomCount[%d]: ", i), + uwslRandomCountList.get(i), totalChars); + } else + { + Household.logHelper(logger, "uwslRandomCount[0]: ", 0, totalChars); + } + Household.logHelper(logger, "aoRandomCount: ", aoRandomCount, totalChars); + Household.logHelper(logger, "fpRandomCount: ", fpRandomCount, totalChars); + Household.logHelper(logger, "cdapRandomCount: ", cdapRandomCount, totalChars); + Household.logHelper(logger, "imtfRandomCount: ", imtfRandomCount, totalChars); + Household.logHelper(logger, "imtodRandomCount: ", imtodRandomCount, totalChars); + Household.logHelper(logger, "immcRandomCount: ", immcRandomCount, totalChars); + Household.logHelper(logger, "awfRandomCount: ", awfRandomCount, totalChars); + Household.logHelper(logger, "awlRandomCount: ", awlRandomCount, totalChars); + Household.logHelper(logger, "awtodRandomCount: ", awtodRandomCount, totalChars); + Household.logHelper(logger, "awmcRandomCount: ", awmcRandomCount, totalChars); + Household.logHelper(logger, "jtfRandomCount: ", jtfRandomCount, totalChars); + Household.logHelper(logger, "jtlRandomCount: ", jtlRandomCount, totalChars); + Household.logHelper(logger, "jtodRandomCount: ", jtodRandomCount, totalChars); + Household.logHelper(logger, "jmcRandomCount: ", jmcRandomCount, totalChars); + Household.logHelper(logger, "inmtfRandomCount: ", inmtfRandomCount, totalChars); + Household.logHelper(logger, "inmtlRandomCount: ", inmtlRandomCount, totalChars); + Household.logHelper(logger, "inmtodRandomCount: ", inmtodRandomCount, totalChars); + Household.logHelper(logger, "inmmcRandomCount: ", inmmcRandomCount, totalChars); + Household.logHelper(logger, "stfRandomCount: ", stfRandomCount, totalChars); + Household.logHelper(logger, "stlRandomCount: ", stlRandomCount, totalChars); + Household.logHelper(logger, "maxAdultOverlaps: ", maxAdultOverlaps, totalChars); + Household.logHelper(logger, "maxChildOverlaps: ", maxChildOverlaps, totalChars); + Household.logHelper(logger, "maxAdultChildOverlaps: ", maxAdultChildOverlaps, totalChars); + + String tempString = String.format("Joint Tours[%s]:", jointTours == null ? "" : String + .valueOf(jointTours.length)); + logger.info(tempString); + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public void logPersonObject(String titleString, Logger logger, PersonIf person) + { + + int totalChars = 114; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "P"; + + logger.info(separater); + logger.info(titleString); + logger.info(separater); + + person.logPersonObject(logger, totalChars); + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public void logTourObject(String titleString, Logger logger, PersonIf person, TourIf tour) + { + + int totalChars = 119; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "T"; + + logger.info(separater); + logger.info(titleString); + logger.info(separater); + + person.logTourObject(logger, totalChars, tour); + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public void logStopObject( String titleString, Logger logger, StopIf stop, ModelStructure modelStructure ) { + + int totalChars = 119; + String separater = ""; + for (int i=0; i < totalChars; i++) + separater += "S"; + + + logger.info( separater ); + logger.info( titleString ); + logger.info( separater ); + + + stop.logStopObject( logger, totalChars ); + + logger.info(separater); + logger.info( "" ); + logger.info( "" ); + + } + + public void logEntireHouseholdObject(String titleString, Logger logger) + { + + int totalChars = 60; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "="; + + logger.info(separater); + logger.info(titleString); + logger.info(separater); + + separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "-"; + + Household.logHelper(logger, "hhId: ", hhId, totalChars); + Household.logHelper(logger, "debugChoiceModels: ", debugChoiceModels ? "True" : "False", + totalChars); + Household.logHelper(logger, "hhIncome: ", hhIncome, totalChars); + Household.logHelper(logger, "hhIncomeInDollars: ", hhIncomeInDollars, totalChars); + Household.logHelper(logger, "hhSize: ", hhSize, totalChars); + Household.logHelper(logger, "hhType: ", hhType, totalChars); + Household.logHelper(logger, "hhWorkers: ", hhWorkers, totalChars); + Household.logHelper(logger, "homeTaz: ", homeTaz, totalChars); + Household.logHelper(logger, "homeWalkSubzone: ", homeWalkSubzone, totalChars); + Household.logHelper(logger, "aoModelAutos: ", aoModelAutos, totalChars); + Household.logHelper(logger, "freeParkingAvailable: ", freeParkingAvailable, totalChars); + Household.logHelper(logger, "cdapModelPattern: ", cdapModelPattern, totalChars); + Household.logHelper(logger, "imtfModelPattern: ", imtfModelPattern, totalChars); + Household.logHelper(logger, "jtfModelPattern: ", jtfModelPattern, totalChars); + Household.logHelper(logger, "randomCount: ", randomCount, totalChars); + if (uwslRandomCountList.size() > 0) + { + for (int i : uwslRandomCountList.keySet()) + Household.logHelper(logger, String.format("uwslRandomCount[%d]: ", i), + uwslRandomCountList.get(i), totalChars); + } else + { + Household.logHelper(logger, "uwslRandomCount[0]: ", 0, totalChars); + } + Household.logHelper(logger, "aoRandomCount: ", aoRandomCount, totalChars); + Household.logHelper(logger, "fpRandomCount: ", fpRandomCount, totalChars); + Household.logHelper(logger, "cdapRandomCount: ", cdapRandomCount, totalChars); + Household.logHelper(logger, "imtfRandomCount: ", imtfRandomCount, totalChars); + Household.logHelper(logger, "imtodRandomCount: ", imtodRandomCount, totalChars); + Household.logHelper(logger, "immcRandomCount: ", immcRandomCount, totalChars); + Household.logHelper(logger, "awfRandomCount: ", awfRandomCount, totalChars); + Household.logHelper(logger, "awlRandomCount: ", awlRandomCount, totalChars); + Household.logHelper(logger, "awtodRandomCount: ", awtodRandomCount, totalChars); + Household.logHelper(logger, "awmcRandomCount: ", awmcRandomCount, totalChars); + Household.logHelper(logger, "jtfRandomCount: ", jtfRandomCount, totalChars); + Household.logHelper(logger, "jtlRandomCount: ", jtlRandomCount, totalChars); + Household.logHelper(logger, "jtodRandomCount: ", jtodRandomCount, totalChars); + Household.logHelper(logger, "jmcRandomCount: ", jmcRandomCount, totalChars); + Household.logHelper(logger, "inmtfRandomCount: ", inmtfRandomCount, totalChars); + Household.logHelper(logger, "inmtlRandomCount: ", inmtlRandomCount, totalChars); + Household.logHelper(logger, "inmtodRandomCount: ", inmtodRandomCount, totalChars); + Household.logHelper(logger, "inmmcRandomCount: ", inmmcRandomCount, totalChars); + Household.logHelper(logger, "stfRandomCount: ", stfRandomCount, totalChars); + Household.logHelper(logger, "stlRandomCount: ", stlRandomCount, totalChars); + Household.logHelper(logger, "maxAdultOverlaps: ", maxAdultOverlaps, totalChars); + Household.logHelper(logger, "maxChildOverlaps: ", maxChildOverlaps, totalChars); + Household.logHelper(logger, "maxAdultChildOverlaps: ", maxAdultChildOverlaps, totalChars); + + if (jointTours != null) + { + logger.info("Joint Tours:"); + if (jointTours.length > 0) + { + for (int i = 0; i < jointTours.length; i++) + jointTours[i].logEntireTourObject(logger); + } else logger.info(" No joint tours"); + } else logger.info(" No joint tours"); + + logger.info("Person Objects:"); + for (int i = 1; i < persons.length; i++) + persons[i].logEntirePersonObject(logger); + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public static void logHelper(Logger logger, String label, int value, int totalChars) + { + int labelChars = label.length() + 2; + int remainingChars = totalChars - labelChars - 4; + String formatString = String.format(" %%%ds %%%dd", label.length(), remainingChars); + String logString = String.format(formatString, label, value); + logger.info(logString); + } + + public static void logHelper(Logger logger, String label, String value, int totalChars) + { + int labelChars = label.length() + 2; + int remainingChars = totalChars - labelChars - 4; + String formatString = String.format(" %%%ds %%%ds", label.length(), remainingChars); + String logString = String.format(formatString, label, value); + logger.info(logString); + } + + public enum HouseholdType + { + nul, FAMILY_MARRIED, FAMILY_MALE_NO_WIFE, FAMILY_FEMALE_NO_HUSBAND, NON_FAMILY_MALE_ALONE, NON_FAMILY_MALE_NOT_ALONE, NON_FAMILY_FEMALE_ALONE, NON_FAMILY_FEMALE_NOT_ALONE + } + + + + public long getHouseholdObjectSize() { + long size = 0; + try{ + size = ObjectUtil.checkObjectSize( this ); + } + catch ( Exception e ){ + } + return size; + } + +} diff --git a/src/java/com/pb/cmap/ctramp/Person.java b/src/java/com/pb/cmap/ctramp/Person.java new file mode 100644 index 0000000..25bf7d0 --- /dev/null +++ b/src/java/com/pb/cmap/ctramp/Person.java @@ -0,0 +1,1956 @@ +package com.pb.cmap.ctramp; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TourIf; + +public class Person implements PersonIf, java.io.Serializable +{ + + // 8 am default departure period + //public static final int DEFAULT_MANDATORY_START_PERIOD = 6; + // 11 am default departure period + public static final int DEFAULT_NON_MANDATORY_START_PERIOD = 12; + // 12 pm default departure period + public static final int DEFAULT_AT_WORK_SUBTOUR_START_PERIOD = 14; + // 5 pm default arrival period + //public static final int DEFAULT_MANDATORY_END_PERIOD = 24; + // 3 pm default arrival period + public static final int DEFAULT_NON_MANDATORY_END_PERIOD = 20; + // 2 pm default arrival period + public static final int DEFAULT_AT_WORK_SUBTOUR_END_PERIOD = 18; + + + + public static final int MIN_ADULT_AGE = 19; + public static final int MIN_STUDENT_AGE = 5; + + // person type strings used for data summaries + public static final String PERSON_TYPE_FULL_TIME_WORKER_NAME = "Full-time worker"; + public static final String PERSON_TYPE_PART_TIME_WORKER_NAME = "Part-time worker"; + public static final String PERSON_TYPE_UNIVERSITY_STUDENT_NAME = "University student"; + public static final String PERSON_TYPE_NON_WORKER_NAME = "Non-worker"; + public static final String PERSON_TYPE_RETIRED_NAME = "Retired"; + public static final String PERSON_TYPE_STUDENT_DRIVING_NAME = "Student of driving age"; + public static final String PERSON_TYPE_STUDENT_NON_DRIVING_NAME = "Student of non-driving age"; + public static final String PERSON_TYPE_PRE_SCHOOL_CHILD_NAME = "Child too young for school"; + + public static final String[] personTypeNameArray = { + PERSON_TYPE_FULL_TIME_WORKER_NAME, PERSON_TYPE_PART_TIME_WORKER_NAME, + PERSON_TYPE_UNIVERSITY_STUDENT_NAME, PERSON_TYPE_NON_WORKER_NAME, + PERSON_TYPE_RETIRED_NAME, PERSON_TYPE_STUDENT_DRIVING_NAME, + PERSON_TYPE_STUDENT_NON_DRIVING_NAME, PERSON_TYPE_PRE_SCHOOL_CHILD_NAME}; + + // Employment category (1-employed FT, 2-employed PT, 3-not employed, 4-under age + // 16) + // Student category (1 - student in grade or high school; 2 - student in college + // or higher; 3 - not a student) + + public static final String EMPLOYMENT_CATEGORY_FULL_TIME_WORKER_NAME = "Full-time worker"; + public static final String EMPLOYMENT_CATEGORY_PART_TIME_WORKER_NAME = "Part-time worker"; + public static final String EMPLOYMENT_CATEGORY_NOT_EMPLOYED_NAME = "Not employed"; + public static final String EMPLOYMENT_CATEGORY_UNDER_AGE_16_NAME = "Under age 16"; + + public static final String[] employmentCategoryNameArray = { + EMPLOYMENT_CATEGORY_FULL_TIME_WORKER_NAME, EMPLOYMENT_CATEGORY_PART_TIME_WORKER_NAME, + EMPLOYMENT_CATEGORY_NOT_EMPLOYED_NAME, EMPLOYMENT_CATEGORY_UNDER_AGE_16_NAME}; + + public static final String STUDENT_CATEGORY_GRADE_OR_HIGH_SCHOOL_NAME = "Grade or high school"; + public static final String STUDENT_CATEGORY_COLLEGE_OR_HIGHER_NAME = "College or higher"; + public static final String STUDENT_CATEGORY_NOT_STUDENT_NAME = "Not student"; + + public static final String[] studentCategoryNameArray = { + STUDENT_CATEGORY_GRADE_OR_HIGH_SCHOOL_NAME, STUDENT_CATEGORY_COLLEGE_OR_HIGHER_NAME, + STUDENT_CATEGORY_NOT_STUDENT_NAME }; + + private Household hhObj; + + private int persNum; + private int persId; + private int persAge; + private int persGender; + private int persPecasOccup; + private int persActivityCode; + private int persEmploymentCategory; + private int persStudentCategory; + private int personType; + private boolean gradeSchool; + private boolean highSchool; + private boolean highSchoolGraduate; + private boolean hasBachelors; + private float persValueOfTime; // individual + // value-of-time + // in + // $/hr + + private int persEduc; + private int persIndCen; + private int persWorkerOccupation; + + private int workLoc; + private int workLocSubzone; + private float workLocDistance; + private float workLocLogsum; + private int schoolLoc; + private int schoolLocSubzone; + private float schoolLocDistance; + private float schoolLocLogsum; + + private int workLocationPurposeIndex; + private int universityLocationPurposeIndex; + private int schoolLocationPurposeIndex; + + private byte freeParkingAvailable; + + private String cdapActivity; + private int imtfChoice; + private int inmtfChoice; + + private int maxAdultOverlaps; + private int maxChildOverlaps; + + private ArrayList workTourArrayList; + private ArrayList schoolTourArrayList; + private ArrayList indNonManTourArrayList; + private ArrayList atWorkSubtourArrayList; + + // private Scheduler scheduler; + // windows[] is 1s based - indexed from 1 to number of intervals. + private byte[] windows; + + private int windowBeforeFirstMandJointTour; + private int windowBetweenFirstLastMandJointTour; + private int windowAfterLastMandJointTour; + + private ModelStructure modelStructure; + + private float walkTimeWeight; + private float walkSpeed; + private float maxWalk; + + private HashMap userClass = new HashMap(); + + public Person(HouseholdIf hhObj, int persNum, ModelStructure modelStructure) + { + this.hhObj = (Household) hhObj; + this.persNum = persNum; + this.workTourArrayList = new ArrayList(); + this.schoolTourArrayList = new ArrayList(); + this.indNonManTourArrayList = new ArrayList(); + this.atWorkSubtourArrayList = new ArrayList(); + this.modelStructure = modelStructure; + + initializeWindows(); + } + + public Tour makeDefaultTour( int purposeIndex ) { + return new Tour( this, purposeIndex ); + } + + public HouseholdIf getHouseholdObject() + { + return hhObj; + } + + public ArrayList getListOfWorkTours() + { + return workTourArrayList; + } + + public ArrayList getListOfSchoolTours() + { + return schoolTourArrayList; + } + + public ArrayList getListOfIndividualNonMandatoryTours() + { + return indNonManTourArrayList; + } + + public ArrayList getListOfAtWorkSubtours() + { + return atWorkSubtourArrayList; + } + + public byte[] getTimeWindows() + { + return windows; + } + + public String getTimePeriodLabel(int windowIndex){ + return modelStructure.getTimePeriodLabel(windowIndex); + } + + public void initializeWindows() + { + windows = new byte[modelStructure.getNumberOfTimePeriods()+1]; + } + + public void resetTimeWindow(int startPeriod, int endPeriod) + { + for (int i = startPeriod; i <= endPeriod; i++) + { + windows[i] = 0; + } + } + + public void resetTimeWindow() + { + for (int i = 0; i < windows.length; i++) + { + windows[i] = 0; + } + } + + /** + * code the time window array for this tour being scheduled. + * 0: unscheduled, + * 1: scheduled, middle of tour, + * 2: scheduled, start of tour, + * 3: scheduled, end of tour, + * 4: scheduled, end of previous tour, start of current tour or + * end of current tour, start of subsequent tour; + * or current tour start/end same period. + * @param start is the departure period index for the tour + * @param end is the arrival period index for the tour + */ + public void scheduleWindow(int start, int end) + { + + /* + * This is the logic used in ARC/MTC, but for SANDAG, we don't allow overlapping tours + * + * + if (start == end) + { + windows[start] = 4; + } else + { + if (windows[start] == 3) windows[start] = 4; + else if (windows[start] == 0) windows[start] = 2; + + if (windows[end] == 2) windows[end] = 4; + else if (windows[end] == 0) windows[end] = 3; + } + + for (int h = start + 1; h < end; h++) + { + windows[h] = 1; + } + */ + + for (int h=start; h <= end; h++) + { + windows[h] = 1; + } + + } + + public boolean[] getAvailableTimeWindows(int[] altStarts, int[] altEnds) + { + + // availability array is used by UEC based choice model, which uses 1-based + // indexing + boolean[] availability = new boolean[altStarts.length + 1]; + + for (int i = 1; i <= altStarts.length; i++) + { + int start = altStarts[i - 1]; + int end = altEnds[i - 1]; + availability[i] = isWindowAvailable(start, end); + } + + return availability; + } + + public boolean isWindowAvailable(int start, int end) + { + + /* + * This is the logic used in ARC/MTC, but for SANDAG, we don't allow overlapping tours + * + * + // check start period, if window is 0, it is unscheduled; + // if window is 3, it is the last period of another tour, and available + // as the first period of this tour. + if (windows[start] == 1) return false; + else if (windows[start] == 2 && start != end) return false; + + // check end period, if window is 0, it is unscheduled; + // if window is 2, it is the first period of another tour, and available + // as the last period of this tour. + if (windows[end] == 1) return false; + else if (windows[end] == 3 && start != end) return false; + + // the alternative is available if start and end are available, and all periods + // from start+1,...,end-1 are available. + for (int h = start + 1; h < end; h++) + { + if (windows[h] > 0) return false; + } + + return true; + */ + + // the alternative is available if all intervals between start and end, inclusive, are available + for (int h=start; h <= end; h++) + { + if (windows[h] > 0) return false; + } + + return true; + + } + + /** + * @return true if the window for the argument is the end of a previously + * scheduled tour and this period does not overlap with any other tour. + */ + public boolean isPreviousArrival(int period) + { + + if (windows[period] == 3 || windows[period] == 4) return true; + else return false; + + } + + /** + * @return true if the window for the argument is the start of a previously + * scheduled tour and this period does not overlap with any other tour. + */ + public boolean isPreviousDeparture(int period) + { + + if (windows[period] == 2 || windows[period] == 4) return true; + else return false; + + } + + public void setPersId(int id) + { + persId = id; + } + + public void setPersAge(int age) + { + persAge = age; + } + + public void setPersGender(int gender) + { + persGender = gender; + } + + public void setPersPecasOccup(int occup) + { + persPecasOccup = occup; + } + + public void setPersActivityCode(int actCode) + { + persActivityCode = actCode; + } + + public void setPersEmploymentCategory(int category) + { + persEmploymentCategory = category; + } + + public void setPersStudentCategory(int category) + { + persStudentCategory = category; + } + + public void setPersonTypeCategory(int personTypeCategory) + { + personType = personTypeCategory; + } + + public void setValueOfTime(float vot) + { + persValueOfTime = vot; + } + + public void setWorkLoc(int loc) + { + workLoc = loc; + } + + public void setWorkLocDistance(float distance) + { + workLocDistance = distance; + } + + public void setWorkLocLogsum(float logsum) + { + workLocLogsum = logsum; + } + + public void setSchoolLoc(int loc) + { + schoolLoc = loc; + } + + public void setSchoolLocDistance(float distance) + { + schoolLocDistance = distance; + } + + public void setSchoolLocLogsum(float logsum) + { + schoolLocLogsum = logsum; + } + + public void setImtfChoice(int choice) + { + imtfChoice = choice; + } + + public void setInmtfChoice(int choice) + { + inmtfChoice = choice; + } + + public int getImtfChoice() + { + return imtfChoice; + } + + public int getInmtfChoice() + { + return inmtfChoice; + } + + public void clearIndividualNonMandatoryToursArray() + { + indNonManTourArrayList.clear(); + } + + + public void clearAtWorkSubtours() + { + + atWorkSubtourArrayList.clear(); + + } + + public void setDailyActivityResult(String activity) + { + this.cdapActivity = activity; + } + + public int getPersonIsChildUnder16WithHomeOrNonMandatoryActivity() + { + + // check the person type + if (persIsStudentNonDrivingAge() == 1 || persIsPreschoolChild() == 1) + { + + // check the activity type + if (cdapActivity.equalsIgnoreCase(ModelStructure.HOME_PATTERN)) return (1); + + if (cdapActivity.equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN)) return (1); + + } + + return (0); + } + + /** + * @return 1 if M, 2 if N, 3 if H + */ + public int getCdapIndex() + { + + // return the activity type + if (cdapActivity.equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN)) return 1; + + if (cdapActivity.equalsIgnoreCase(ModelStructure.NONMANDATORY_PATTERN)) return 2; + + if (cdapActivity.equalsIgnoreCase(ModelStructure.HOME_PATTERN)) return 3; + + return (0); + } + + public int getPersonIsChild6To18WithoutMandatoryActivity() + { + + // check the person type + if (persIsStudentDrivingAge() == 1 || persIsStudentNonDrivingAge() == 1) + { + + // check the activity type + if (cdapActivity.equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN)) return 0; + else return 1; + + } + + return 0; + } + + // methods DMU will use to get info from household object + + public int getAge() + { + return persAge; + } + + public int getHomemaker() + { + return persIsHomemaker(); + } + + public int getGender() + { + return persGender; + } + + public int getPersonIsFemale() + { + if (persGender == 2) return 1; + return 0; + } + + public int getPersonIsMale() + { + if (persGender == 1) return 1; + return 0; + } + + public int getPersonId() + { + return this.persId; + } + + public int getPersonNum() + { + return this.persNum; + } + + public String getPersonType() + { + return personTypeNameArray[personType - 1]; + } + + public void setPersonIsHighSchool(boolean flag) + { + highSchool = flag; + } + + public int getPersonIsHighSchool() + { + return highSchool ? 1 : 0; + } + + public void setPersonIsGradeSchool(boolean flag) + { + gradeSchool = flag; + } + + public int getPersonIsGradeSchool() + { + return gradeSchool ? 1 : 0; + } + + public int getPersonIsHighSchoolGraduate() + { + return highSchoolGraduate ? 1 : 0; + } + + public void setPersonIsHighSchoolGraduate(boolean hsGrad) + { + highSchoolGraduate = hsGrad; + } + + public void setPersonHasBachelors(boolean hasBS) + { + hasBachelors = hasBS; + } + + public int getPersonTypeNumber() + { + return personType; + } + + public int getPersPecasOccup() + { + return persPecasOccup; + } + + public int getPersActivityCode() + { + return persActivityCode; + } + + public int getPersonEmploymentCategoryIndex() + { + return persEmploymentCategory; + } + + public String getPersonEmploymentCategory() + { + return employmentCategoryNameArray[persEmploymentCategory - 1]; + } + + public int getPersonStudentCategoryIndex() + { + return persStudentCategory; + } + + public String getPersonStudentCategory() + { + return studentCategoryNameArray[persStudentCategory - 1]; + } + + public float getValueOfTime() + { + return persValueOfTime; + } + + public int getPersonWorkLocationZone() + { + return workLoc; + } + + public int getPersonSchoolLocationZone() + { + return schoolLoc; + } + + public String getCdapActivity() + { + return cdapActivity; + } + + public int getUsualWorkLocation() + { + return workLoc; + } + + public float getWorkLocationDistance() + { + return workLocDistance; + } + + public float getWorkLocationLogsum() + { + return workLocLogsum; + } + + public int getUsualSchoolLocation() + { + return schoolLoc; + } + + public float getSchoolLocationDistance() + { + return schoolLocDistance; + } + + public float getSchoolLocationLogsum() + { + return schoolLocLogsum; + } + + public int getHasBachelors() + { + return hasBachelors ? 1 : 0; + } + + public int getNumWorkTours() + { + ArrayList workTours = getListOfWorkTours(); + if (workTours != null) return workTours.size(); + else return 0; + } + + public int getNumSchoolTours() + { + ArrayList schoolTours = getListOfSchoolTours(); + if (schoolTours != null) return schoolTours.size(); + else return 0; + } + + public int getNumIndividualEscortTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.ESCORT_PURPOSE_NAME)) num++; + return num; + } + + public int getNumIndividualShoppingTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.SHOPPING_PURPOSE_NAME)) + num++; + return num; + } + + public int getNumIndividualEatOutTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.EAT_OUT_PURPOSE_NAME)) num++; + return num; + } + + public int getNumIndividualOthMaintTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.OTH_MAINT_PURPOSE_NAME)) + num++; + return num; + } + + public int getNumIndividualSocialTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.SOCIAL_PURPOSE_NAME)) num++; + return num; + } + + public int getNumIndividualOthDiscrTours() + { + int num = 0; + for (TourIf tour : getListOfIndividualNonMandatoryTours()) + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(modelStructure.OTH_DISCR_PURPOSE_NAME)) + num++; + return num; + } + + public int getNumMandatoryTours() + { + int numTours = 0; + ArrayList workTours = getListOfWorkTours(); + if (workTours != null) numTours += workTours.size(); + + ArrayList schoolTours = getListOfSchoolTours(); + if (schoolTours != null) numTours += schoolTours.size(); + + return numTours; + } + + public int getNumNonMandatoryTours() + { + ArrayList nonMandTours = getListOfIndividualNonMandatoryTours(); + if (nonMandTours == null) return 0; + else return nonMandTours.size(); + } + + public int getNumSubtours() + { + ArrayList subtours = getListOfAtWorkSubtours(); + if (subtours == null) return 0; + else return subtours.size(); + } + + public int getNumTotalIndivTours() + { + return getNumMandatoryTours() + getNumNonMandatoryTours() + getNumSubtours(); + } + + public int getNumJointShoppingTours() + { + return getNumJointToursForPurpose(modelStructure.SHOPPING_PURPOSE_NAME); + } + + public int getNumJointOthMaintTours() + { + return getNumJointToursForPurpose(modelStructure.OTH_MAINT_PURPOSE_NAME); + } + + public int getNumJointEatOutTours() + { + return getNumJointToursForPurpose(modelStructure.EAT_OUT_PURPOSE_NAME); + } + + public int getNumJointSocialTours() + { + return getNumJointToursForPurpose(modelStructure.SOCIAL_PURPOSE_NAME); + } + + public int getNumJointOthDiscrTours() + { + return getNumJointToursForPurpose(modelStructure.OTH_DISCR_PURPOSE_NAME); + } + + private int getNumJointToursForPurpose(String purposeName) + { + int count = 0; + TourIf[] jt = hhObj.getJointTourArray(); + if (jt == null) return count; + + for (int i = 0; i < jt.length; i++) + if (jt[i].getTourPrimaryPurpose().equalsIgnoreCase(purposeName)) count++; + + return count; + } + + public void computeIdapResidualWindows() + { + + // find the start of the earliest mandatory or joint tour for this person + // and end of last one. + int firstTourStart = 9999; + int lastTourEnd = -1; + int firstTourEnd = 0; + int lastTourStart = 0; + + // first check mandatory tours + for (TourIf tour : workTourArrayList) + { + int tourDeparts = tour.getTourDepartPeriod(); + int tourArrives = tour.getTourArrivePeriod(); + + if (tourDeparts < firstTourStart) + { + firstTourStart = tourDeparts; + firstTourEnd = tourArrives; + } + + if (tourArrives > lastTourEnd) + { + lastTourStart = tourDeparts; + lastTourEnd = tourArrives; + } + } + + for (TourIf tour : schoolTourArrayList) + { + int tourDeparts = tour.getTourDepartPeriod(); + int tourArrives = tour.getTourArrivePeriod(); + + if (tourDeparts < firstTourStart) + { + firstTourStart = tourDeparts; + firstTourEnd = tourArrives; + } + + if (tourArrives > lastTourEnd) + { + lastTourStart = tourDeparts; + lastTourEnd = tourArrives; + } + } + + // now check joint tours + TourIf[] jointTourArray = hhObj.getJointTourArray(); + if (jointTourArray != null) + { + for (TourIf tour : jointTourArray) + { + + if (tour == null) continue; + + // see if this person is in the joint tour or not + if (tour.getPersonInJointTour(this)) + { + + int tourDeparts = tour.getTourDepartPeriod(); + int tourArrives = tour.getTourArrivePeriod(); + + if (tourDeparts < firstTourStart) + { + firstTourStart = tourDeparts; + firstTourEnd = tourArrives; + } + + if (tourArrives > lastTourEnd) + { + lastTourStart = tourDeparts; + lastTourEnd = tourArrives; + } + + } + + } + } + + if (firstTourStart > modelStructure.getNumberOfTimePeriods() - 1 && lastTourEnd < 0) + { + int numPeriods = windows.length; + windowBeforeFirstMandJointTour = numPeriods; + windowAfterLastMandJointTour = numPeriods; + windowBetweenFirstLastMandJointTour = numPeriods; + } else + { + + // since first tour first period and last tour last period are available, + // account for them. + windowBeforeFirstMandJointTour = firstTourStart + 1; + windowAfterLastMandJointTour = modelStructure.getNumberOfTimePeriods() - lastTourEnd; + + // find the number of unscheduled periods between end of first tour and + // start of last tour + windowBetweenFirstLastMandJointTour = 0; + for (int i = firstTourEnd; i <= lastTourStart; i++) + { + if (isPeriodAvailable(i)) windowBetweenFirstLastMandJointTour++; + } + } + + } + + public int getWindowBeforeFirstMandJointTour() + { + return windowBeforeFirstMandJointTour; + } + + public int getWindowBetweenFirstLastMandJointTour() + { + return windowBetweenFirstLastMandJointTour; + } + + public int getWindowAfterLastMandJointTour() + { + return windowAfterLastMandJointTour; + } + + // public int getNumberOfMandatoryWorkTours( String workPurposeName ){ + // + // int numberOfTours = 0; + // for(int i=0;i= MIN_ADULT_AGE + && persEmploymentCategory == EmployStatus.NOT_EMPLOYED.ordinal()) return 1; + else return 0; + } + + public int notEmployed() + { + if (persEmploymentCategory == EmployStatus.NOT_EMPLOYED.ordinal()) return 1; + else return 0; + } + + private int persIsWorker() + { + if (persEmploymentCategory == EmployStatus.FULL_TIME.ordinal() + || persEmploymentCategory == EmployStatus.PART_TIME.ordinal()) return 1; + else return 0; + } + + private int persIsStudent() + { + if (persStudentCategory == StudentStatus.STUDENT_HIGH_SCHOOL_OR_LESS.ordinal() + || persStudentCategory == StudentStatus.STUDENT_COLLEGE_OR_HIGHER.ordinal()) + { + return 1; + } else + { + return 0; + } + } + + private int persIsFullTimeWorker() + { + if (persEmploymentCategory == EmployStatus.FULL_TIME.ordinal()) return 1; + else return 0; + } + + private int persIsPartTimeWorker() + { + if (persEmploymentCategory == EmployStatus.PART_TIME.ordinal()) return 1; + else return 0; + } + + private int persTypeIsFullTimeWorker() + { + if (personType == PersonType.FT_worker_age_16plus.ordinal()) return 1; + else return 0; + } + + private int persTypeIsPartTimeWorker() + { + if (personType == PersonType.PT_worker_nonstudent_age_16plus.ordinal()) return 1; + else return 0; + } + + private int persIsUniversity() + { + if (personType == PersonType.University_student.ordinal()) return 1; + else return 0; + } + + private int persIsStudentDrivingAge() + { + if (personType == PersonType.Student_age_16_19_not_FT_wrkr_or_univ_stud.ordinal()) return 1; + else return 0; + } + + private int persIsStudentNonDrivingAge() + { + if (personType == PersonType.Student_age_6_15_schpred.ordinal()) return 1; + else return 0; + } + + private int persIsPreschoolChild() + { + if (personType == PersonType.Preschool_under_age_6.ordinal()) return 1; + else return 0; + + } + + private int persIsNonWorkingAdultUnder65() + { + if (personType == PersonType.Nonworker_nonstudent_age_16_64.ordinal()) return 1; + else return 0; + } + + private int persIsNonWorkingAdultOver65() + { + if (personType == PersonType.Nonworker_nonstudent_age_65plus.ordinal()) + { + return 1; + } else + { + return 0; + } + } + + /** + * return maximum periods of overlap between this person and other adult persons in + * the household. + * + * @return the most number of periods mutually available between this person and + * other adult household members + */ + public int getMaxAdultOverlaps() + { + return maxAdultOverlaps; + } + + /** + * set maximum periods of overlap between this person and other adult persons in + * the household. + * + * @param overlaps are the most number of periods mutually available between this + * person and other adult household members + */ + public void setMaxAdultOverlaps(int overlaps) + { + maxAdultOverlaps = overlaps; + } + + /** + * return maximum periods of overlap between this person and other children in the + * household. + * + * @return the most number of periods mutually available between this person and + * other child household members + */ + public int getMaxChildOverlaps() + { + return maxChildOverlaps; + } + + /** + * set maximum periods of overlap between this person and other children in the + * household. + * + * @param overlaps are the most number of periods mutually available between this + * person and other child household members + */ + public void setMaxChildOverlaps(int overlaps) + { + maxChildOverlaps = overlaps; + } + + /** + * return available time window for this person in the household. + * + * @return the total number of periods available for this person + */ + public int getAvailableWindow() + { + int numPeriodsAvailable = 0; + for (int i = 1; i < windows.length; i++) + if (windows[i] != 1) numPeriodsAvailable++; + + return numPeriodsAvailable; + } + + /** + * determine the maximum consecutive available time window for the person + * + * @return the length of the maximum available window in units of time intervals + */ + public int getMaximumContinuousAvailableWindow() + { + int maxWindow = 0; + int currentWindow = 0; + for (int i = 1; i < windows.length; i++){ + if (windows[i] == 0){ + currentWindow++; + } + else{ + if (currentWindow > maxWindow) + maxWindow = currentWindow; + currentWindow = 0; + } + } + if (currentWindow > maxWindow) + maxWindow = currentWindow; + + return maxWindow; + } + + /** + * determine the maximum consecutive pairwise available time window for this person + * and the person for which a window was passed + * + * @return the length of the maximum pairwise available window in units of time intervals + */ + public int getMaximumContinuousPairwiseAvailableWindow( byte[] otherWindow ) + { + int maxWindow = 0; + int currentWindow = 0; + for (int i = 1; i < windows.length; i++){ + if (windows[i] == 0 && otherWindow[i] == 0){ + currentWindow++; + } + else{ + if (currentWindow > maxWindow) + maxWindow = currentWindow; + currentWindow = 0; + } + } + if (currentWindow > maxWindow) + maxWindow = currentWindow; + + return maxWindow; + } + + public void setTimeWindows(byte[] win) + { + windows = win; + } + + public void initializeForAoRestart() + { + + cdapActivity = "-"; + imtfChoice = 0; + inmtfChoice = 0; + + maxAdultOverlaps = 0; + maxChildOverlaps = 0; + + workTourArrayList.clear(); + schoolTourArrayList.clear(); + indNonManTourArrayList.clear(); + atWorkSubtourArrayList.clear(); + + initializeWindows(); + + windowBeforeFirstMandJointTour = 0; + windowBetweenFirstLastMandJointTour = 0; + windowAfterLastMandJointTour = 0; + + } + + public void initializeForImtfRestart() + { + + imtfChoice = 0; + inmtfChoice = 0; + + maxAdultOverlaps = 0; + maxChildOverlaps = 0; + + workTourArrayList.clear(); + schoolTourArrayList.clear(); + indNonManTourArrayList.clear(); + atWorkSubtourArrayList.clear(); + + initializeWindows(); + + windowBeforeFirstMandJointTour = 0; + windowBetweenFirstLastMandJointTour = 0; + windowAfterLastMandJointTour = 0; + + } + + /** + * initialize the person attributes and tour objects for restarting the model at + * joint tour frequency + */ + public void initializeForJtfRestart() + { + + inmtfChoice = 0; + + indNonManTourArrayList.clear(); + atWorkSubtourArrayList.clear(); + + for (int i = 0; i < workTourArrayList.size(); i++) + { + TourIf t = workTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + for (int i = 0; i < schoolTourArrayList.size(); i++) + { + TourIf t = schoolTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + + windowBeforeFirstMandJointTour = 0; + windowBetweenFirstLastMandJointTour = 0; + windowAfterLastMandJointTour = 0; + + } + + /** + * initialize the person attributes and tour objects for restarting the model at + * individual non-mandatory tour frequency. + */ + public void initializeForInmtfRestart() + { + + inmtfChoice = 0; + + indNonManTourArrayList.clear(); + atWorkSubtourArrayList.clear(); + + for (int i = 0; i < workTourArrayList.size(); i++) + { + TourIf t = workTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + for (int i = 0; i < schoolTourArrayList.size(); i++) + { + TourIf t = schoolTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + + windowBeforeFirstMandJointTour = 0; + windowBetweenFirstLastMandJointTour = 0; + windowAfterLastMandJointTour = 0; + + } + + /** + * initialize the person attributes and tour objects for restarting the model at + * at-work sub-tour frequency. + */ + public void initializeForAwfRestart() + { + + atWorkSubtourArrayList.clear(); + + for (int i = 0; i < workTourArrayList.size(); i++) + { + TourIf t = workTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + for (int i = 0; i < schoolTourArrayList.size(); i++) + { + TourIf t = schoolTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + for (int i = 0; i < indNonManTourArrayList.size(); i++) + { + TourIf t = indNonManTourArrayList.get(i); + scheduleWindow(t.getTourDepartPeriod(), t.getTourArrivePeriod()); + t.clearStopModelResults(); + } + + } + + /** + * initialize the person attributes and tour objects for restarting the model at + * stop frequency. + */ + public void initializeForStfRestart() + { + + for (int i = 0; i < workTourArrayList.size(); i++) + { + TourIf t = workTourArrayList.get(i); + t.clearStopModelResults(); + } + for (int i = 0; i < schoolTourArrayList.size(); i++) + { + TourIf t = schoolTourArrayList.get(i); + t.clearStopModelResults(); + } + for (int i = 0; i < atWorkSubtourArrayList.size(); i++) + { + TourIf t = atWorkSubtourArrayList.get(i); + t.clearStopModelResults(); + } + for (int i = 0; i < indNonManTourArrayList.size(); i++) + { + TourIf t = indNonManTourArrayList.get(i); + t.clearStopModelResults(); + } + + } + + public void logPersonObject(Logger logger, int totalChars) + { + + Household.logHelper(logger, "persNum: ", persNum, totalChars); + Household.logHelper(logger, "persId: ", persId, totalChars); + Household.logHelper(logger, "persAge: ", persAge, totalChars); + Household.logHelper(logger, "persGender: ", persGender, totalChars); + Household.logHelper(logger, "persEmploymentCategory: ", persEmploymentCategory, totalChars); + Household.logHelper(logger, "persStudentCategory: ", persStudentCategory, totalChars); + Household.logHelper(logger, "personType: ", personType, totalChars); + Household.logHelper(logger, "workLoc: ", workLoc, totalChars); + Household.logHelper(logger, "schoolLoc: ", schoolLoc, totalChars); + Household.logHelper(logger, "cdapActivity: ", cdapActivity, totalChars); + Household.logHelper(logger, "imtfChoice: ", imtfChoice, totalChars); + Household.logHelper(logger, "inmtfChoice: ", inmtfChoice, totalChars); + Household.logHelper(logger, "maxAdultOverlaps: ", maxAdultOverlaps, totalChars); + Household.logHelper(logger, "maxChildOverlaps: ", maxChildOverlaps, totalChars); + Household.logHelper(logger, "windowBeforeFirstMandJointTour: ", + windowBeforeFirstMandJointTour, totalChars); + Household.logHelper(logger, "windowBetweenFirstLastMandJointTour: ", + windowBetweenFirstLastMandJointTour, totalChars); + Household.logHelper(logger, "windowAfterLastMandJointTour: ", windowAfterLastMandJointTour, + totalChars); + + String header1 = " Index: |"; + String header2 = " Period: |"; + String windowString = " Window: |"; + String periodString = ""; + for (int i = 1; i < windows.length; i++) + { + header1 += String.format(" %2d |", i); + header2 += String.format("%4s|", modelStructure.getTimePeriodLabel(i)); + switch (windows[i]) + { + case 0: + periodString = " "; + break; + case 1: + periodString = "XXXX"; + break; + } + windowString += String.format("%4s|", periodString); + } + + logger.info(header1); + logger.info(header2); + logger.info(windowString); + + if (workTourArrayList.size() > 0) + { + for (TourIf tour : workTourArrayList) + { + int id = tour.getTourId(); + logger.info(tour.getTourWindow(String.format("W%d", id))); + } + } + if (atWorkSubtourArrayList.size() > 0) + { + for (TourIf tour : atWorkSubtourArrayList) + { + int id = tour.getTourId(); + String alias = ""; + String purposeName = tour.getSubTourPurpose(); + if (purposeName.equalsIgnoreCase(modelStructure.AT_WORK_BUSINESS_PURPOSE_NAME)) alias = "aB"; + else if (purposeName.equalsIgnoreCase(modelStructure.AT_WORK_EAT_PURPOSE_NAME)) alias = "aE"; + else if (purposeName.equalsIgnoreCase(modelStructure.AT_WORK_MAINT_PURPOSE_NAME)) + alias = "aM"; + logger.info(tour.getTourWindow(String.format("%s%d", alias, id))); + } + } + if (schoolTourArrayList.size() > 0) + { + for (TourIf tour : schoolTourArrayList) + { + int id = tour.getTourId(); + String alias = "S"; + logger.info(tour.getTourWindow(String.format("%s%d", alias, id))); + } + } + if (hhObj.getJointTourArray() != null && hhObj.getJointTourArray().length > 0) + { + for (TourIf tour : hhObj.getJointTourArray()) + { + if (tour == null) continue; + + // log this persons time window if they are in the joint tour party. + byte[] persNumArray = tour.getPersonNumArray(); + if (persNumArray != null) + { + for (int num : persNumArray) + { + if (num == persNum) + { + + Person person = (Person)hhObj.getPersons()[num]; + tour.setPersonObject(person); + + int id = tour.getTourId(); + String alias = ""; + if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME)) alias = "jE"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME)) alias = "jS"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME)) alias = "jM"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.VISITING_PRIMARY_PURPOSE_NAME)) alias = "jV"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME)) alias = "jD"; + logger.info(tour.getTourWindow(String.format("%s%d", alias, id))); + } + } + } + } + } + if (indNonManTourArrayList.size() > 0) + { + for (TourIf tour : indNonManTourArrayList) + { + int id = tour.getTourId(); + String alias = ""; + if (tour.getTourPrimaryPurpose().equalsIgnoreCase(ModelStructure.ESCORT_PRIMARY_PURPOSE_NAME)) alias = "ie"; + else if (tour.getTourPrimaryPurpose() + .equalsIgnoreCase(ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME)) alias = "iE"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME)) alias = "iS"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME)) alias = "iM"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.VISITING_PRIMARY_PURPOSE_NAME)) alias = "iV"; + else if (tour.getTourPrimaryPurpose().equalsIgnoreCase( + ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME)) alias = "iD"; + logger.info(tour.getTourWindow(String.format("%s%d", alias, id))); + } + } + + } + + public void logTourObject(Logger logger, int totalChars, TourIf tour) + { + tour.logTourObject(logger, totalChars); + } + + public void logEntirePersonObject(Logger logger) + { + + int totalChars = 60; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "-"; + + Household.logHelper(logger, "persNum: ", persNum, totalChars); + Household.logHelper(logger, "persId: ", persId, totalChars); + Household.logHelper(logger, "persAge: ", persAge, totalChars); + Household.logHelper(logger, "persGender: ", persGender, totalChars); + Household.logHelper(logger, "persEmploymentCategory: ", persEmploymentCategory, totalChars); + Household.logHelper(logger, "persStudentCategory: ", persStudentCategory, totalChars); + Household.logHelper(logger, "personType: ", personType, totalChars); + Household.logHelper(logger, "workLoc: ", workLoc, totalChars); + Household.logHelper(logger, "schoolLoc: ", schoolLoc, totalChars); + Household.logHelper(logger, "cdapActivity: ", cdapActivity, totalChars); + Household.logHelper(logger, "imtfChoice: ", imtfChoice, totalChars); + Household.logHelper(logger, "inmtfChoice: ", inmtfChoice, totalChars); + Household.logHelper(logger, "maxAdultOverlaps: ", maxAdultOverlaps, totalChars); + Household.logHelper(logger, "maxChildOverlaps: ", maxChildOverlaps, totalChars); + Household.logHelper(logger, "windowBeforeFirstMandJointTour: ", + windowBeforeFirstMandJointTour, totalChars); + Household.logHelper(logger, "windowBetweenFirstLastMandJointTour: ", + windowBetweenFirstLastMandJointTour, totalChars); + Household.logHelper(logger, "windowAfterLastMandJointTour: ", windowAfterLastMandJointTour, + totalChars); + + String header = " Period: |"; + String windowString = " Window: |"; + for (int i = 1; i < windows.length; i++) + { + header += String.format("%4s|", modelStructure.getTimePeriodLabel(i)); + windowString += String.format("%4s|", windows[i] == 0 ? " " : "XXXX"); + } + + logger.info(header); + logger.info(windowString); + + if (workTourArrayList.size() > 0) + { + for (TourIf tour : workTourArrayList) + { + int id = tour.getTourId(); + logger.info(tour.getTourWindow(String.format("W%d", id))); + } + } + if (schoolTourArrayList.size() > 0) + { + for (TourIf tour : schoolTourArrayList) + { + logger.info(tour + .getTourWindow(tour.getTourPrimaryPurpose().equalsIgnoreCase("university") ? "U" + : "S")); + } + } + if (indNonManTourArrayList.size() > 0) + { + for (TourIf tour : indNonManTourArrayList) + { + logger.info(tour.getTourWindow("N")); + } + } + if (atWorkSubtourArrayList.size() > 0) + { + for (TourIf tour : atWorkSubtourArrayList) + { + logger.info(tour.getTourWindow("A")); + } + } + if (hhObj.getJointTourArray() != null && hhObj.getJointTourArray().length > 0) + { + for (TourIf tour : hhObj.getJointTourArray()) + { + if (tour != null) logger.info(tour.getTourWindow("J")); + } + } + + logger.info(separater); + + logger.info("Work Tours:"); + if (workTourArrayList.size() > 0) + { + for (TourIf tour : workTourArrayList) + { + tour.logEntireTourObject(logger); + } + } else + { + logger.info(" No work tours"); + } + + logger.info("School Tours:"); + if (schoolTourArrayList.size() > 0) + { + for (TourIf tour : schoolTourArrayList) + { + tour.logEntireTourObject(logger); + } + } else + { + logger.info(" No school tours"); + } + + logger.info("Individual Non-mandatory Tours:"); + if (indNonManTourArrayList.size() > 0) + { + for (TourIf tour : indNonManTourArrayList) + { + tour.logEntireTourObject(logger); + } + } else + { + logger.info(" No individual non-mandatory tours"); + } + + logger.info("Work based subtours Tours:"); + if (atWorkSubtourArrayList.size() > 0) + { + for (TourIf tour : atWorkSubtourArrayList) + { + tour.logEntireTourObject(logger); + } + } else + { + logger.info(" No work based subtours"); + } + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public enum EmployStatus + { + nul, FULL_TIME, PART_TIME, NOT_EMPLOYED, UNDER16 + } + + public enum StudentStatus + { + nul, STUDENT_HIGH_SCHOOL_OR_LESS, STUDENT_COLLEGE_OR_HIGHER, NON_STUDENT + } + + public enum PersonType + { + nul, FT_worker_age_16plus, PT_worker_nonstudent_age_16plus, University_student, Nonworker_nonstudent_age_16_64, Nonworker_nonstudent_age_65plus, Student_age_16_19_not_FT_wrkr_or_univ_stud, Student_age_6_15_schpred, Preschool_under_age_6 + } + + + + + public void setFreeParkingAvailableResult( int fpResult ) { + freeParkingAvailable = (byte)fpResult; + } + + public int getFreeParkingAvailableResult() { + return freeParkingAvailable; + } + + + public void setWorkLocSubzone( int subzone ) { + workLocSubzone = subzone; + } + + public void setSchoolLocSubzone( int subzone ) { + schoolLocSubzone = subzone; + } + + public void setWorkLocationPurposeIndex( int workPurpose ) { + workLocationPurposeIndex = workPurpose; + } + + public void setUniversityLocationPurposeIndex( int universityPurpose ) { + universityLocationPurposeIndex = universityPurpose; + } + + public void setSchoolLocationPurposeIndex( int schoolPurpose ) { + schoolLocationPurposeIndex = schoolPurpose; + } + + public int getPersonSchoolLocationSubZone() { + return schoolLocSubzone; + } + + public int getPersonWorkLocationSubZone() { + return workLocSubzone; + } + + public int getSchoolLocationPurposeIndex() { + return schoolLocationPurposeIndex; + } + + public int getUniversityLocationPurposeIndex() { + return universityLocationPurposeIndex; + } + + public int getWorkLocationPurposeIndex() { + return workLocationPurposeIndex; + } + + public int getNumUniversityTours() { + int num = 0; + for ( TourIf tour : getListOfSchoolTours() ) + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.UNIVERSITY_PRIMARY_PURPOSE_NAME ) ) + num++; + return num; + } + + public void createIndividualNonMandatoryTours( int numberOfTours, String purposeName, ModelStructure modelStructure ){ + + // if purpose is escort, need to determine if household has kids or not + if ( purposeName.equalsIgnoreCase( ModelStructure.ESCORT_PURPOSE_NAME ) & modelStructure.getNumEscortSegments() > 0 ) { + if ( hhObj.getNumChildrenUnder19() > 0 ) + purposeName += "_" + modelStructure.ESCORT_SEGMENT_NAMES[0]; + else + purposeName += "_" + modelStructure.ESCORT_SEGMENT_NAMES[1]; + } + + int primaryPurposeIndex = modelStructure.getPrimaryPurposeIndex( modelStructure.getPrimaryPurposeString(purposeName) ); + + int startId = indNonManTourArrayList.size(); + + for(int i=0;i= tourDepartPeriod && i <= tourArrivePeriod ? purposeAbbreviation : " " ); + if ( tempString.length() == 2 || tempString.length() == 3 ) + tempString = " " + tempString; + returnString += String.format("%4s|", tempString ); + } + return returnString; + } + + public void logTourObject(Logger logger, int totalChars) + { + + String personNumArrayString = "-"; + if (personNumArray != null) + { + personNumArrayString = "[ "; + personNumArrayString += String.format("%d", personNumArray[0]); + for (int i = 1; i < personNumArray.length; i++) + personNumArrayString += String.format(", %d", personNumArray[i]); + personNumArrayString += " ]"; + } + + Household.logHelper(logger, "tourId: ", tourId, totalChars); + Household.logHelper(logger, "tourCategory: ", tourCategory, totalChars); + Household.logHelper(logger, "tourPurpose: ", tourPurpose, totalChars); + Household.logHelper(logger, "tourPurposeIndex: ", tourPrimaryPurposeIndex, totalChars); + Household.logHelper(logger, "personNumArray: ", personNumArrayString, totalChars); + Household.logHelper(logger, "jointTourComposition: ", jointTourComposition, totalChars); + Household.logHelper(logger, "tourOrigTaz: ", tourOrigTaz, totalChars); + Household.logHelper(logger, "tourDestTaz: ", tourDestTaz, totalChars); + Household.logHelper(logger, "tourOrigWalkSubzone: ", tourOrigWalkSubzone, totalChars); + Household.logHelper(logger, "tourDestWalkSubzone: ", tourDestWalkSubzone, totalChars); + Household.logHelper(logger, "tourDepartPeriod: ", tourDepartPeriod, totalChars); + Household.logHelper(logger, "tourArrivePeriod: ", tourArrivePeriod, totalChars); + Household.logHelper(logger, "tourMode: ", tourMode, totalChars); + Household.logHelper(logger, "stopFreqChoice: ", stopFreqChoice, totalChars); + + String tempString = String.format("outboundStops[%s]:", outboundStops == null ? "" : String + .valueOf(outboundStops.length)); + logger.info(tempString); + + tempString = String.format("inboundStops[%s]:", inboundStops == null ? "" : String + .valueOf(inboundStops.length)); + logger.info(tempString); + + } + + public void logEntireTourObject(Logger logger) + { + + int totalChars = 60; + String separater = ""; + for (int i = 0; i < totalChars; i++) + separater += "-"; + + String personNumArrayString = "-"; + if (personNumArray != null) + { + personNumArrayString = "[ "; + personNumArrayString += String.format("%d", personNumArray[0]); + for (int i = 1; i < personNumArray.length; i++) + personNumArrayString += String.format(", %d", personNumArray[i]); + personNumArrayString += " ]"; + } + + Household.logHelper(logger, "tourId: ", tourId, totalChars); + Household.logHelper(logger, "tourCategory: ", tourCategory, totalChars); + Household.logHelper(logger, "tourPurpose: ", tourPurpose, totalChars); + Household.logHelper(logger, "tourPurposeIndex: ", tourPrimaryPurposeIndex, totalChars); + Household.logHelper(logger, "personNumArray: ", personNumArrayString, totalChars); + Household.logHelper(logger, "jointTourComposition: ", jointTourComposition, totalChars); + Household.logHelper(logger, "tourOrigTaz: ", tourOrigTaz, totalChars); + Household.logHelper(logger, "tourDestTaz: ", tourDestTaz, totalChars); + Household.logHelper(logger, "tourOrigWalkSubzone: ", tourOrigWalkSubzone, totalChars); + Household.logHelper(logger, "tourDestWalkSubzone: ", tourDestWalkSubzone, totalChars); + Household.logHelper(logger, "tourDepartPeriod: ", tourDepartPeriod, totalChars); + Household.logHelper(logger, "tourArrivePeriod: ", tourArrivePeriod, totalChars); + Household.logHelper(logger, "tourMode: ", tourMode, totalChars); + Household.logHelper(logger, "stopFreqChoice: ", stopFreqChoice, totalChars); + + if (outboundStops != null) + { + logger.info("Outbound Stops:"); + if (outboundStops.length > 0) + { + for (int i = 0; i < outboundStops.length; i++) + outboundStops[i].logStopObject(logger, totalChars); + } else + { + logger.info(" No outbound stops"); + } + } else + { + logger.info(" No outbound stops"); + } + + if (inboundStops != null) + { + logger.info("Inbound Stops:"); + if (inboundStops.length > 0) + { + for (int i = 0; i < inboundStops.length; i++) + inboundStops[i].logStopObject(logger, totalChars); + } else + { + logger.info(" No inbound stops"); + } + } else + { + logger.info(" No inbound stops"); + } + + logger.info(separater); + logger.info(""); + logger.info(""); + + } + + public void setTourModalUtilities(float[] utils) + { + tourModalUtilities = utils; + } + + public float[] getTourModalUtilities() + { + return tourModalUtilities; + } + + public void setTourModalProbabilities(float[] probs) + { + tourModalProbabilities = probs; + } + + public float[] getTourModalProbabilities() + { + return tourModalProbabilities; + } + + public byte getTourCategoryIndex() { + return tourCategoryIndex; + } + + public boolean getTourCategoryIsMandatory() { + return tourCategoryIndex == ModelStructure.MANDATORY_CATEGORY_INDEX; + } + + public boolean getTourCategoryIsAtWork() { + return tourCategoryIndex == ModelStructure.AT_WORK_CATEGORY_INDEX; + } + + public boolean getTourCategoryIsJointNonMandatory() { + return tourCategoryIndex == ModelStructure.JOINT_NON_MANDATORY_CATEGORY_INDEX; + } + + public boolean getTourCategoryIsIndivNonMandatory() { + return tourCategoryIndex == ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY_INDEX; + } + + public int getWorkTourIndexFromSubtourId( int subtourId ) { + // when subtour was created, it's purpose index was set to 10*(work purpose index + 1) + at-work subtour index + return (subtourId / 10) - 1; + } + + public int getSubtourIdFromIndices(int workTourIndex, int subtourIndex ) { + // this is used to create the sutour, it's purpose index was set to 10*(work purpose index + 1) + at-work subtour index + return 10*(workTourIndex+1) + subtourIndex; + } + +} diff --git a/src/java/com/pb/cmap/synpop/ARCPopulationSynthesizer.java b/src/java/com/pb/cmap/synpop/ARCPopulationSynthesizer.java new file mode 100644 index 0000000..f2c2156 --- /dev/null +++ b/src/java/com/pb/cmap/synpop/ARCPopulationSynthesizer.java @@ -0,0 +1,90 @@ +/* + * Copyright 2007 PB Americas, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.synpop; + +import java.util.ResourceBundle; +import java.util.Vector; + +import com.pb.common.util.ResourceUtil; +import com.pb.models.synpopV3.PopulationSynthesizer; + +/** + * Calls the synpopV3 model for use with the ARC project. Also calls John Bowman's Aggregator + * class to produce trip-based model input. + * + * @author D. Ory + * + */ + +public class ARCPopulationSynthesizer extends PopulationSynthesizer { + + public ARCPopulationSynthesizer() { + super("cmap", new DerivedHHARCFactory()); + } + + public ARCPopulationSynthesizer(String propertiesRoot){ + super(propertiesRoot, new DerivedHHARCFactory()); + } + +// public void createDerivedHHFactory(){ +// hhFactory = new DerivedHHARCFactory(); +// } + + public static void main(String[] args) { + + // use the MTC-version of the resource bundle, and inherited derived household class + Vector[][] synPop; + PopulationSynthesizer arcPopulationSynthesizer = new ARCPopulationSynthesizer(); + synPop = arcPopulationSynthesizer.runPopulationSynthesizer(); + + // run the aggregator if requested + ResourceBundle resourceBundle = ResourceUtil.getResourceBundle("cmap"); + boolean runAggregator = ResourceUtil.getBooleanProperty(resourceBundle, "RunAggregator"); + if(runAggregator){ + + // user feedback + logger.info("Running Aggregator post process..."); + + // create Bowman's master data dictionary object + String pumsDirectory = ResourceUtil.getProperty(resourceBundle, "pums.directory"); + String pumsDictionary = ResourceUtil.getProperty(resourceBundle, "pums.dictionary"); + pumsDictionary = pumsDirectory+pumsDictionary; + + String masterDictonaryFile = ResourceUtil.getProperty(resourceBundle, "MasterDataDictionaryInputFile"); + + MasterDataDictionary masterDataDictionary = new MasterDataDictionary(pumsDictionary,masterDictonaryFile); + logger.info("Number of Master Data Dictionary entries: "+masterDataDictionary.entries.size()); + + // create Bowman's aggregator to read from control file and set up aggregationSpecs + Aggregator aggregator=new Aggregator(masterDataDictionary); + int n = aggregator.getNumberOfAggregations(); + + // loop to produce aggregations + for(int i=1; i<=n; i++){ + aggregator.aggregate(synPop, aggregator.getAggregationSpec(i)); + //note: aggregate produces output and returns aggregation object, but the object is not here used. + } + + } + + logger.info(" "); + logger.info("End: ARC Population Synthesizer"); + + + } + +} diff --git a/src/java/com/pb/cmap/synpop/Aggregator.java b/src/java/com/pb/cmap/synpop/Aggregator.java new file mode 100644 index 0000000..d673b19 --- /dev/null +++ b/src/java/com/pb/cmap/synpop/Aggregator.java @@ -0,0 +1,404 @@ +/* + * Copyright 2007 John L. Bowman + * You may not use this file without a license for its use. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.pb.cmap.synpop; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.LinkedHashMap; +import java.util.Vector; + +import org.apache.log4j.Logger; + +import static java.lang.Math.*; + +import com.pb.common.matrix.NDimensionalMatrix; +import com.pb.models.synpopV3.DrawnHH; +import com.pb.models.synpopV3.PropertyParser; + + +/** + * @author John L Bowman + * + * Created on Mar 5, 2007 + * + * -------------------------------------------------------------------------------------------- + * + * JLB 20070305 This program aggregates + * --one or more classes specified in properties file + * --in one or more categorizations specified in properties + * file + * +*/ + +public class Aggregator { + protected boolean logDebug=false; + protected static Logger logger = Logger.getLogger("com.pb.arc.synpop"); + + protected LinkedHashMap aggregationSpecs; + protected int numberOfAggregations; + protected MasterDataDictionary mdd; + protected String outputDirectory; + + public Aggregator(MasterDataDictionary mdd){ + this.mdd=mdd; + Vector dimensionVariables; + AggregationSpec aggregationSpec; + + // Read aggregator parameters from properties file + outputDirectory = PropertyParser.getPropertyByName("Aggregator.OutputDirectory"); + numberOfAggregations = new Integer(PropertyParser.getPropertyByName("Aggregator.NumberOfAggregations")).intValue(); + aggregationSpecs = new LinkedHashMap(); + + // Loop to read parameters of each aggregation specified in properties file + for(int i=1; i<=numberOfAggregations; i++){ + String si = String.valueOf(i); + + aggregationSpec = new AggregationSpec(); + aggregationSpec.aggregationNumber = i; + aggregationSpec.aggregationParameters.put("Item", "DerivedHH"); + aggregationSpec.aggregationParameters.put("Statistic", "Count"); + aggregationSpec.aggregationParameters.put("Geography", "TAZ"); + aggregationSpec.aggregationParameters.put("Outfile", "Aggregation1.csv"); + aggregationSpec.aggregationParameters.put("OutfileType", "ascii"); + aggregationSpec.aggregationParameters.put("OutfileDelimiter", "Comma"); + aggregationSpec.aggregationParameters.put("IncludeOutfileHeader", "true"); + aggregationSpec.aggregationParameters.put("CategoryLabelType", "Descriptions"); + aggregationSpec.dimensionVarnames.put("1","hsizecat6"); + aggregationSpec.dimensionVarnames.put("2","hinccat1"); + aggregationSpec.dimensionVarnames.put("3","hwrkcat5"); + aggregationSpec.dimensionVarnames.put("4","hNCcat6"); + aggregationSpec.dimensionSizes.put("1", "6"); + aggregationSpec.dimensionSizes.put("2", "4"); + aggregationSpec.dimensionSizes.put("3", "5"); + aggregationSpec.dimensionSizes.put("4", "6"); + + if(!PropertyParser.getPropertyByName("Aggregator."+si+".Item").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "Item", + PropertyParser.getPropertyByName("Aggregator."+si+".Item").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".Statistic").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "Statistic", + PropertyParser.getPropertyByName("Aggregator."+si+".Statistic").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".Geography").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "Geography", + PropertyParser.getPropertyByName("Aggregator."+si+".Geography").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".Outfile").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "Outfile", + PropertyParser.getPropertyByName("Aggregator."+si+".Outfile").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".OutfileType").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "OutfileType", + PropertyParser.getPropertyByName("Aggregator."+si+".OutfileType").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".OutfileDelimiter").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "OutfileDelimiter", + PropertyParser.getPropertyByName("Aggregator."+si+".OutfileDelimiter").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".IncludeOutfileHeader").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "IncludeOutfileHeader", + PropertyParser.getPropertyByName("Aggregator."+si+".IncludeOutfileHeader").trim()); + if(!PropertyParser.getPropertyByName("Aggregator."+si+".CategoryLabelType").trim().equals(null)) + aggregationSpec.aggregationParameters.put( + "CategoryLabelType", + PropertyParser.getPropertyByName("Aggregator."+si+".CategoryLabelType").trim()); + + dimensionVariables=PropertyParser.getPropertyElementsByName("Aggregator."+si+".DimensionVariables",","); + if (!dimensionVariables.isEmpty()) { + aggregationSpec.dimensionVarnames.clear(); + aggregationSpec.dimensionSizes.clear(); + for(int j=1; j<=dimensionVariables.size(); j++){ + String sj = String.valueOf(j); + String dimensionVariable = (String)dimensionVariables.get(j-1); + aggregationSpec.dimensionVarnames.put( + sj, + dimensionVariable); + aggregationSpec.dimensionSizes.put( + sj, + String.valueOf(mdd.getNumberOfValues(dimensionVariable))); + } + aggregationSpecs.put(i,aggregationSpec); + } + } + } + public int getNumberOfAggregations() { + return numberOfAggregations; + } + + public AggregationSpec getAggregationSpec(int i) { + return (AggregationSpec)aggregationSpecs.get(i); + } + + private class AggregationSpec { + protected int aggregationNumber; + protected LinkedHashMap aggregationParameters; // + protected LinkedHashMap dimensionSizes; // + protected LinkedHashMap dimensionVarnames; // + + /* + * Constructor (empty) + */ + public AggregationSpec() { + aggregationParameters=new LinkedHashMap(); + dimensionSizes=new LinkedHashMap(); + dimensionVarnames=new LinkedHashMap(); + aggregationNumber=0; + } + public int getNumberOfDimensions(){ + return dimensionSizes.size(); + } + public int getDimensionSize(int dimension){ + return Integer.valueOf((String)dimensionSizes.get(String.valueOf(dimension))); + } + public String getDimensionVarname(int dimension){ + return (String)dimensionVarnames.get(String.valueOf(dimension)); + } + public String getAggregationParameter(String key){ + return (String)aggregationParameters.get(key); + } + public int getAggregationNumber(){ + return (int)aggregationNumber; + } + } + + public NDimensionalMatrix aggregate(Vector [][] PopSyn, AggregationSpec aS){ + NDimensionalMatrix aggregation; + /*Note: should capture and log exceptions. Simple handling would be adequate, + such as skipping to next aggregation after reporting exception + */ + + // initialize aggregation matrix and work variables, using info from aS and mdd. + int length = aS.getNumberOfDimensions(); + int[] shape = new int[length]; + int maxshape = 0; + int[] position = new int[length]; + String[] varname = new String[length]; + for(int i=1; i<=length; i++){ + shape[i-1] = aS.getDimensionSize(i); + if(shape[i-1] > maxshape) maxshape = shape[i-1]; + position[i-1] = 0; + varname[i-1] = aS.getDimensionVarname(i); + } + String[][] varIndex = new String[length][maxshape]; + for(int i=0; i7) logger.warn ("Aggregation dimensions exceed limit of 7; no output written for aggregation "+aS.getAggregationNumber()); + else{ + for(int i1=0; i11){ + for(int i2=0; i22){ + for(int i3=0; i33){ + for(int i4=0; i44){ + for(int i5=0; i55){ + for(int i6=0; i66){ + for(int i7=0; i70){ + //cycle through all dimensions printing index, then print aggregation value + for(int k=0; k=18) wrkrcount2++; + } + } + + if(wrkrcount2>=4) hwrkcat5 = 4; + else hwrkcat5=wrkrcount2; + + + } + + /** + * Sets the number of children in household variable + * Bowman's function + */ + private void setHNCcat6(){ + + Set keySet = pRecordsMap.keySet(); + Iterator itr = keySet.iterator(); + String key=new String(); + PUMSPerson person; + int age; + while (itr.hasNext()) { + key = (String) itr.next(); + person=(PUMSPerson)pRecordsMap.get(key); + age=person.getPAttr("AGE"); + + if(age<=17) hNCcat6++; + } + + if (hNCcat6>5) hNCcat6=5; + + } + + + + + + +} diff --git a/src/java/com/pb/cmap/synpop/DerivedHHARCFactory.java b/src/java/com/pb/cmap/synpop/DerivedHHARCFactory.java new file mode 100644 index 0000000..af50793 --- /dev/null +++ b/src/java/com/pb/cmap/synpop/DerivedHHARCFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007 PB Americas + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.synpop; + +import java.util.Vector; + +import com.pb.models.synpopV3.DataDictionary; +import com.pb.models.synpopV3.DerivedHHFactory; + +/** + * A class that creates DerivedHH objects + * + * @author D. Ory (same as Erhardt DerivedHHSFFactory) + * @version 1.0 Oct 19, 2007 + * + */ +public class DerivedHHARCFactory extends DerivedHHFactory { + + + public DerivedHHARCFactory() { + super(); + } + + public DerivedHHARC createDerivedHH(String record_raw, Vector pRecords_raw, DataDictionary dd) { + DerivedHHARC hh = new DerivedHHARC(record_raw, pRecords_raw, dd); + return hh; + } + +} diff --git a/src/java/com/pb/cmap/synpop/MasterDataDictionary.java b/src/java/com/pb/cmap/synpop/MasterDataDictionary.java new file mode 100644 index 0000000..0e3e77b --- /dev/null +++ b/src/java/com/pb/cmap/synpop/MasterDataDictionary.java @@ -0,0 +1,715 @@ +/* + * Copyright 2007 John L. Bowman + * You may not use this file without a license for its use. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.pb.cmap.synpop; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.apache.log4j.Logger; + +import com.pb.models.synpopV3.PUMSAttrs; +import com.pb.models.synpopV3.PropertyParser; + +/** + * @author John L Bowman + * + * Created on Mar 13, 2007 + * + * -------------------------------------------------------------------------------------------- + * + * JLB 20070317 This program + * --creates a repository for + * --data item definitions + * --data item value definitions + * --retrieves PUMS data item and data value definitions from an ascii PUMS definitions file + * --retrieves other data item and data value definitions from a tab delimited definitions file + * --provides methods to add individual data item and value definitions to the repository + * (this feature not used on initial implementation) + * +*/ + +public class MasterDataDictionary{ + public static final boolean DEBUG = false; + protected static Logger logger = Logger.getLogger(MasterDataDictionary.class.getName()); + //data item name<--->data item definition object + public LinkedHashMap entries; + + /** + * CONSTRUCTORS AND BASIC METHODS + */ + + /** + * Constructor--construct empty dictionary + */ + public MasterDataDictionary(){ + entries=new LinkedHashMap(); + } + + /** + * Constructor--construct dictionary with PUMS definitions + */ + public MasterDataDictionary(String PUMSDefFileName){ + entries=new LinkedHashMap(); + readPUMSMasterDDEntries(PUMSDefFileName); + setValueIndices(entries); + } + + /** + * Constructor--construct dictionary with PUMS and Other definitions + */ + public MasterDataDictionary(String PUMSDefFileName, String DefFileName){ + entries=new LinkedHashMap(); + readPUMSMasterDDEntries(PUMSDefFileName); + readMasterDDEntries(DefFileName); + setValueIndices(entries); + } + +// public void putEntry(String itemName, DataItemDefinition definition){ + private void putEntry(String itemName, DataItemDefinition definition){ + entries.put(itemName, definition); + } + + public DataItemDefinition getDataItemDefinition(String itemName){ +// private DataItemDefinition getDataItemDefinition(String itemName){ + return (DataItemDefinition)entries.get(itemName); + } + + + /** + * DATA ITEM DEFINITION CLASS WITH CONSTRUCTORS AND BASIC METHODS + */ + + private class DataItemDefinition { + private String itemName; + private String shortDescription; + private String longDescription; + private String type; + private int length; + private String primaryClass; + protected LinkedHashMap valueDefinitions; // + protected LinkedHashMap rangeDefinitions; // + + /* + * Constructor for item definition + * --without supplied value definitions + * --without short description + */ + public DataItemDefinition(String itemName, + String type, + int length, + String primaryClass, + String longDescription + ) { + this.itemName=itemName; + this.type=type; + this.length = length; + this.primaryClass=primaryClass; + this.longDescription=longDescription; + shortDescription=" "; + valueDefinitions=new LinkedHashMap(); + rangeDefinitions=new LinkedHashMap(); + } + + /* + * Constructor for item definition + * --without supplied value definitions + * --with shortDescription + */ + public DataItemDefinition(String itemName, + String type, + int length, + String primaryClass, + String longDescription, + String shortDescription + ) { + this.itemName=itemName; + this.type=type; + this.length = length; + this.primaryClass=primaryClass; + this.longDescription=longDescription; + this.shortDescription=shortDescription; + valueDefinitions=new LinkedHashMap(); + rangeDefinitions=new LinkedHashMap(); + } + +// public void putValueDefinition(String stringValue, ValueDefinition definition){ + private void putValueDefinition(String stringValue, ValueDefinition definition){ + valueDefinitions.put(stringValue,definition); + } + +// public void putRangeDefinition(String rangeBottom, RangeDefinition definition){ + private void putRangeDefinition(String rangeBottom, RangeDefinition definition){ + rangeDefinitions.put(rangeBottom,definition); + } + } + + /** + * DATA VALUE DEFINITION CLASS WITH CONSTRUCTORS + */ + +// public class ValueDefinition { + private class ValueDefinition { + private String itemName; + private String stringValue; + private int integerValue; + private String shortDescription; + private String longDescription; + private int valueIndex; + + /* + * Constructor for integer values + */ + public ValueDefinition(String itemName, int integerValue, String description){ + this.itemName=itemName; + this.integerValue=integerValue; + this.stringValue=""+integerValue; + this.longDescription=description; + this.shortDescription=" "; + this.valueIndex=-999999; + + } + + /* + * Constructor for string values + */ + public ValueDefinition(String itemName, int integerValue, String stringValue, String description){ + this.itemName=itemName; + this.integerValue= integerValue; + this.stringValue=stringValue; + this.longDescription=description; + this.shortDescription=" "; + this.valueIndex=-999999; + } + + /* + * Constructor for string values + * --with short description + */ + public ValueDefinition(String itemName, + int integerValue, + String stringValue, + String longDescription, + String shortDescription){ + this.itemName=itemName; + this.integerValue= integerValue; + this.stringValue=stringValue; + this.longDescription=longDescription; + this.shortDescription=shortDescription; + this.valueIndex=-999999; + } + + } + + /** + * DATA RANGE DEFINITION CLASS WITH CONSTRUCTORS + */ + + private class RangeDefinition { + private String itemName; + private int integerRangeBottom; + private int integerRangeTop; + private String stringRangeBottom; + private String stringRangeTop; + private String shortDescription; + private String longDescription; + + /* + * Constructor for ranges + * --without short description + */ + public RangeDefinition(String itemName, + int integerRangeBottom, + int integerRangeTop, + String stringRangeBottom, + String stringRangeTop, + String description){ + this.itemName=itemName; + this.integerRangeBottom=integerRangeBottom; + this.integerRangeTop=integerRangeTop; + this.stringRangeBottom=stringRangeBottom; + this.stringRangeTop=stringRangeTop; + this.longDescription=description; + this.shortDescription=" "; + } + /* + * Constructor for ranges + * --with short description + */ + public RangeDefinition(String itemName, + int integerRangeBottom, + int integerRangeTop, + String stringRangeBottom, + String stringRangeTop, + String longDescription, + String shortDescription){ + this.itemName=itemName; + this.integerRangeBottom=integerRangeBottom; + this.integerRangeTop=integerRangeTop; + this.stringRangeBottom=stringRangeBottom; + this.stringRangeTop=stringRangeTop; + this.longDescription=longDescription; + this.shortDescription=shortDescription; + } + } + + /* + * METHODS THAT ARE USED TO FILL THE DATA DICTIONARY + */ + + /* + * Put a single data item definition into the data dictionary + * without accompanying value and range definitions + */ + public void createDataItemDefinition( + String itemName, + String type, + int length, + String primaryClass, + String longDescription, + String shortDescription) { + DataItemDefinition dID = new DataItemDefinition ( + itemName, + type, + length, + primaryClass, + longDescription, + shortDescription); + putEntry(itemName, dID); + } + + /* + * Create a single value definition + * and put it into its data item definition + * within the data dictionary, given its data item name + * and the other details of its defintion + */ + public void createValueDefinition( + String itemName, + int integerValue, + String stringValue, + String longDescription, + String shortDescription){ + ValueDefinition vD = new ValueDefinition (itemName, + integerValue, + stringValue, + longDescription, + shortDescription); + getDataItemDefinition(itemName).putValueDefinition(stringValue, vD); + } + + /* + * Create a single range definition + * and put it into its data item definition + * within the data dictionary, given its data item name + * and the other details of its defintion + */ + public void createRangeDefinition( + String itemName, + int integerRangeBottom, + int integerRangeTop, + String stringRangeBottom, + String stringRangeTop, + String longDescription, + String shortDescription){ + RangeDefinition rD = new RangeDefinition (itemName, + integerRangeBottom, + integerRangeTop, + stringRangeBottom, + stringRangeTop, + longDescription, + shortDescription); + getDataItemDefinition(itemName).putRangeDefinition(stringRangeBottom, rD); + } + + /* + * Read all the PUMS data definitions from an ascii file and put those + * that have been selected in the Properties file into the dictionary, + * including data item definitions and all accompanying value and + * range definitions. + */ + private void readPUMSMasterDDEntries(String fileName) { + int tokenCount; + int RECTYPECount = 0; + String primaryClass = null; + //HH attributes, from property file + Vector hhAttrs; + //person attributes, from property file + Vector personAttrs; + String itemName = null; + int length=0; + String itemDescription; + int integerRangeBottom; + int integerRangeTop; + String stringRangeBottom; + String stringRangeTop; + String stringValue; + int integerValue; + String description; + DataItemDefinition dataItemDefinition = null; + ValueDefinition valueDefinition = null; + RangeDefinition rangeDefinition = null; + boolean matchPUMSList = false; + int ii=0; + //get HH attribute names + hhAttrs=PUMSAttrs.getHHAttrs(); + //get HH attribute names + personAttrs=PUMSAttrs.getPersonAttrs(); + + try { + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String s = new String(); + // skip the first record (header) which defines fields + s = in.readLine(); ii=1; + while ((s = in.readLine()) != null) { + ii=ii+1; + if (s.length() > 0) { + String[] result = s.split(" ",2); + String[] result2 = result[1].split(" ",0); + if (result[0].trim().equalsIgnoreCase("D")) { + matchPUMSList=false; + length = Integer.valueOf(result2[1]); + if (result2[0].trim().equalsIgnoreCase("RECTYPE")){ + RECTYPECount++; + } + else { + switch(RECTYPECount){ + case 1: { + for(int i = 0; i=1) stringValue=""+stV.nextToken().trim(); + else stringValue = "-99999"; + if ((stringValue.equalsIgnoreCase("blank")) + || (stringValue.substring(stringValue.length()-1).equalsIgnoreCase("+"))) + integerValue = -99999; + else if (stringValue.substring(0,1).matches("\\D")) //non-digit is interpreted as minus sign + integerValue = (-1)* Integer.valueOf(stringValue.substring(1)); + else if (stringValue.length()>2){ + if (stringValue.substring(2,3).equalsIgnoreCase(" ")) integerValue = -99999; + else integerValue = Integer.valueOf(stringValue); + } + else integerValue = Integer.valueOf(stringValue); + if (tokenCount>=2) description=stV.nextToken().trim(); + else description = ""; + valueDefinition = new ValueDefinition(itemName, integerValue, stringValue, description); + dataItemDefinition.putValueDefinition(stringValue, valueDefinition); + } + else if (result[0].trim().equalsIgnoreCase("R")){ + StringTokenizer stR = new StringTokenizer(result[1],"."); + tokenCount = stR.countTokens(); + if (tokenCount>=1){ + stringRangeBottom=""+stR.nextToken().trim(); + if (stringRangeBottom.substring(0,1).matches("\\D")) //non-digit is interpreted as minus sign + integerRangeBottom = (-1)* Integer.valueOf(stringRangeBottom.substring(1)); + else if (stringRangeBottom.length()>2){ + if (stringRangeBottom.substring(2,3).equalsIgnoreCase(" ")) integerRangeBottom = -99999; + else integerRangeBottom = Integer.valueOf(stringRangeBottom); + } + else integerRangeBottom = Integer.valueOf(stringRangeBottom); + }else{ + stringRangeBottom="-99999"; + integerRangeBottom=-99999; + } + if (tokenCount>=2){ + stringRangeTop=""+stR.nextToken().trim(); + if (stringRangeTop.substring(0,1).matches("\\D")) //non-digit is interpreted as minus sign + integerRangeTop = (-1)* Integer.valueOf(stringRangeTop.substring(1)); + else if (stringRangeTop.length()>2){ + if (stringRangeTop.substring(2,3).equalsIgnoreCase(" ")) integerRangeTop = -99999; + else integerRangeTop = Integer.valueOf(stringRangeTop); + } + else integerRangeTop = Integer.valueOf(stringRangeTop); + }else{ + stringRangeTop="-99999"; + integerRangeTop=-99999; + } + if (integerRangeBottom > integerRangeTop){ + int tempInt=integerRangeBottom; + integerRangeBottom=integerRangeTop; + integerRangeTop=tempInt; + String tempString = stringRangeBottom; + stringRangeBottom = stringRangeTop; + stringRangeTop = tempString; + } + if (tokenCount>=3)description=stR.nextToken().trim(); + else description = ""; + rangeDefinition = new RangeDefinition(itemName, + integerRangeBottom, + integerRangeTop, + stringRangeBottom, + stringRangeTop, + description); + dataItemDefinition.putRangeDefinition(stringRangeBottom, rangeDefinition); + } + } + } + } + } + } catch (Exception e) { + logger.fatal( + "IO Exception caught reading PUMS data defs file: " +fileName+" line "+ii); + e.printStackTrace(); + } + } + + + + private void readMasterDDEntries(String fileName) { + int ii=0; + String itemName = null; + String primaryClass = null; + int length = 0; + String type = null; + String shortDescription = null; + String longDescription = null; + int integerRangeTop=0; + String stringRangeTop=null; + String stringValue; + int integerValue; + DataItemDefinition dataItemDefinition = null; + ValueDefinition valueDefinition = null; + RangeDefinition rangeDefinition = null; + + try { + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String s = new String(); + // skip the first record (header) + s = in.readLine();ii++; + while ((s = in.readLine()) != null) { + ii++; + if (s.length() > 0) { +// String[] result = s.split(",",-2); + String[] result = s.split("\t",-2); + if (result.length>=9){ + itemName=result[1].trim(); + primaryClass=result[2].trim(); + length=(Integer.valueOf(result[3].trim())); + if (result[4].trim().equalsIgnoreCase("I")) type="int"; + else if (result[4].trim().equalsIgnoreCase("S")) type="String"; + else { + type = "String"; + logger.warn("Assumed String for undefined type code in def input line "+ ii); + } + longDescription = result[7].trim(); + shortDescription = result[8].trim(); + if (result[0].trim().equalsIgnoreCase("I")) { + dataItemDefinition=new DataItemDefinition( + itemName, + type, + length, + primaryClass, + longDescription, + shortDescription); + putEntry(itemName, dataItemDefinition); + } + else if ((result[0].trim().equalsIgnoreCase("V")) + ||(result[0].trim().equalsIgnoreCase("R"))){ + stringValue=result[5].trim(); + if (!type.equalsIgnoreCase("int")){ + integerValue = 0; + integerRangeTop = 0; + } + else{ + if (stringValue.length() > 1){ + if (stringValue.substring(0,1).matches("\\D")) //non-digit is interpreted as minus sign + integerValue = (-1)* Integer.valueOf(stringValue.substring(1)); + else integerValue = Integer.valueOf(stringValue); + } + else integerValue = Integer.valueOf(stringValue); + if (result[0].trim().equalsIgnoreCase("R")){ + stringRangeTop=result[6].trim(); + if (stringRangeTop.length() > 1){ + if (stringRangeTop.substring(0,1).matches("\\D")) //non-digit is interpreted as minus sign + integerRangeTop = (-1)* Integer.valueOf(stringRangeTop.substring(1)); + else integerRangeTop = Integer.valueOf(stringRangeTop); + } + else integerRangeTop = Integer.valueOf(stringRangeTop); + } + } + if (result[0].trim().equalsIgnoreCase("V")){ + valueDefinition = new ValueDefinition( + itemName, + integerValue, + stringValue, + longDescription, + shortDescription); + dataItemDefinition.putValueDefinition(stringValue, valueDefinition); + } + if (result[0].trim().equalsIgnoreCase("R")){ + rangeDefinition = new RangeDefinition( + itemName, + integerValue, + integerRangeTop, + stringValue, + stringRangeTop, + longDescription, + shortDescription); + dataItemDefinition.putRangeDefinition(stringValue, rangeDefinition); + } + } + }else logger.warn("Incomplete data definition input at line "+ ii); + } else logger.info("Empty data definition input line "+ ii); + } + } catch (Exception e) { + logger.fatal( + "IO Exception caught reading data defs file: " +fileName+" line "+ii); + e.printStackTrace(); + } + } + + // Read all values of all data items and assign 0-based index to all values of each data item + // This was created so that Aggregator could use the 0-based index as array index, rather than actual values + private void setValueIndices(LinkedHashMap entries){ + int mddSize = entries.size(); + String [] dKeys; +// = new String[mddSize]; + dKeys=(String[])entries.keySet().toArray(new String[mddSize]); + for(int i=0; i(); + + methodIndexMap.put( "getHhIncomeCategory", 0 ); + methodIndexMap.put( "getNumAutos", 1 ); + methodIndexMap.put( "getPersonIsFullTimeWorker", 2 ); + methodIndexMap.put( "getPersonIsNonworker", 3 ); + methodIndexMap.put( "getWorkTazAreaType", 4 ); + methodIndexMap.put( "getWorkTourDuration", 5 ); + methodIndexMap.put( "getJointMaintShopEatPerson", 6 ); + methodIndexMap.put( "getJointDiscrPerson", 7 ); + methodIndexMap.put( "getIndivMaintShopEscortFt", 8 ); + methodIndexMap.put( "getIndivMaintShopEscortPt", 9 ); + methodIndexMap.put( "getIndivDiscrFt", 10 ); + methodIndexMap.put( "getIndivDiscrPt", 11 ); + methodIndexMap.put( "getIndivEatOut", 12 ); + methodIndexMap.put( "getWorkTourModeIsSOV", 13 ); + methodIndexMap.put( "getNumPersonWorkTours", 14 ); + methodIndexMap.put( "getWorkStudNonMandatoryTours", 15 ); + } + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getHhIncomeCategory(); + case 1: return getNumAutos(); + case 2: return getPersonIsFullTimeWorker(); + case 3: return getPersonIsNonworker(); + case 4: return getWorkTazAreaType(); + case 5: return getWorkTourDuration(); + case 6: return getJointMaintShopEatPerson(); + case 7: return getJointDiscrPerson(); + case 8: return getIndivMaintShopEscortFt(); + case 9: return getIndivMaintShopEscortPt(); + case 10: return getIndivDiscrFt(); + case 11: return getIndivDiscrPt(); + case 12: return getIndivEatOut(); + case 13: return getWorkTourModeIsSOV(); + case 14: return getNumPersonWorkTours(); + case 15: return getWorkStudNonMandatoryTours(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapAutoOwnershipChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapAutoOwnershipChoiceDMU.java new file mode 100644 index 0000000..414803b --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapAutoOwnershipChoiceDMU.java @@ -0,0 +1,69 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.AutoOwnershipChoiceDMU; + + +public class CmapAutoOwnershipChoiceDMU extends AutoOwnershipChoiceDMU { + + + public CmapAutoOwnershipChoiceDMU() { + super (); + setupMethodIndexMap(); + } + + public int getHhIncome() { + return hh.getIncomeSegment(); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getSize", 0 ); + methodIndexMap.put( "getNumChildrenUnder16", 1 ); + methodIndexMap.put( "getDrivers", 2 ); + methodIndexMap.put( "getWorkers", 3 ); + methodIndexMap.put( "getStudents", 4 ); + methodIndexMap.put( "getNumPersons16to17", 5 ); + methodIndexMap.put( "getNumPersons18to24", 6 ); + methodIndexMap.put( "getHhIncome", 7 ); + methodIndexMap.put( "getWorkAutoDependency", 8 ); + methodIndexMap.put( "getSchoolAutoDependency", 9 ); + methodIndexMap.put( "getHhBldgsz", 10 ); + methodIndexMap.put( "getAccess17", 11 ); + methodIndexMap.put( "getAccess18", 12 ); + methodIndexMap.put( "getNumPersons65to79", 13 ); + methodIndexMap.put( "getNumPersons80plus", 14 ); + + } + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getSize(); + case 1: return getNumChildrenUnder16(); + case 2: return getDrivers(); + case 3: return getWorkers(); + case 4: return getStudents(); + case 5: return getNumPersons16to17(); + case 6: return getNumPersons18to24(); + case 7: return getHhIncome(); + case 8: return getWorkAutoDependency(); + case 9: return getSchoolAutoDependency(); + case 10: return getHhBldgsz(); + case 11: return getAccess17(); + case 12: return getAccess18(); + case 13: return getNumPersons65to79(); + case 14: return getNumPersons80plus(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapCoordinatedDailyActivityPatternDMU.java b/src/java/com/pb/cmap/tourBased/CmapCoordinatedDailyActivityPatternDMU.java new file mode 100644 index 0000000..89b249a --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapCoordinatedDailyActivityPatternDMU.java @@ -0,0 +1,129 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.CoordinatedDailyActivityPatternDMU; + + +public class CmapCoordinatedDailyActivityPatternDMU extends CoordinatedDailyActivityPatternDMU { + + + + public CmapCoordinatedDailyActivityPatternDMU() { + super (); + setupMethodIndexMap(); + } + + + // household income + // TODO make sure this is the right income (check where in syn pop file it comes from) + public int getIncomeLess20k(){ + int incomeQuartile = householdObject.getIncomeSegment(); + if(incomeQuartile==1) return 1; + return 0; + } + + public int getIncome50to100k(){ + int incomeQuartile = householdObject.getIncomeSegment(); + if(incomeQuartile==3) return 1; + return 0; + } + + public int getIncomeMore100k(){ + int incomeQuartile = householdObject.getIncomeSegment(); + if(incomeQuartile==4) return 1; + return 0; + } + + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getFullTimeWorkerA", 0 ); + methodIndexMap.put( "getFullTimeWorkerB", 1 ); + methodIndexMap.put( "getFullTimeWorkerC", 2 ); + methodIndexMap.put( "getPartTimeWorkerA", 3 ); + methodIndexMap.put( "getPartTimeWorkerB", 4 ); + methodIndexMap.put( "getPartTimeWorkerC", 5 ); + methodIndexMap.put( "getUniversityStudentA", 6 ); + methodIndexMap.put( "getUniversityStudentB", 7 ); + methodIndexMap.put( "getUniversityStudentC", 8 ); + methodIndexMap.put( "getNonWorkingAdultA", 9 ); + methodIndexMap.put( "getNonWorkingAdultB", 10 ); + methodIndexMap.put( "getNonWorkingAdultC", 11 ); + methodIndexMap.put( "getRetiredA", 12 ); + methodIndexMap.put( "getRetiredB", 13 ); + methodIndexMap.put( "getRetiredC", 14 ); + methodIndexMap.put( "getDrivingAgeSchoolChildA", 15 ); + methodIndexMap.put( "getDrivingAgeSchoolChildB", 16 ); + methodIndexMap.put( "getDrivingAgeSchoolChildC", 17 ); + methodIndexMap.put( "getPreDrivingAgeSchoolChildA", 18 ); + methodIndexMap.put( "getPreDrivingAgeSchoolChildB", 19 ); + methodIndexMap.put( "getPreDrivingAgeSchoolChildC", 20 ); + methodIndexMap.put( "getPreSchoolChildA", 21 ); + methodIndexMap.put( "getPreSchoolChildB", 22 ); + methodIndexMap.put( "getPreSchoolChildC", 23 ); + methodIndexMap.put( "getAgeA", 24 ); + methodIndexMap.put( "getFemaleA", 25 ); + methodIndexMap.put( "getMoreCarsThanWorkers", 26 ); + methodIndexMap.put( "getFewerCarsThanWorkers", 27 ); + methodIndexMap.put( "getIncomeLess20k", 28 ); + methodIndexMap.put( "getIncome50to100k", 29 ); + methodIndexMap.put( "getIncomeMore100k", 30 ); + methodIndexMap.put( "getUsualWorkLocationIsHome", 31 ); + methodIndexMap.put( "getNoUsualWorkLocation", 32 ); + methodIndexMap.put( "getNoUsualSchoolLocation", 33 ); + methodIndexMap.put( "getHhSize", 34 ); + } + + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getFullTimeWorkerA(); + case 1: return getFullTimeWorkerB(); + case 2: return getFullTimeWorkerC(); + case 3: return getPartTimeWorkerA(); + case 4: return getPartTimeWorkerB(); + case 5: return getPartTimeWorkerC(); + case 6: return getUniversityStudentA(); + case 7: return getUniversityStudentB(); + case 8: return getUniversityStudentC(); + case 9: return getNonWorkingAdultA(); + case 10: return getNonWorkingAdultB(); + case 11: return getNonWorkingAdultC(); + case 12: return getRetiredA(); + case 13: return getRetiredB(); + case 14: return getRetiredC(); + case 15: return getDrivingAgeSchoolChildA(); + case 16: return getDrivingAgeSchoolChildB(); + case 17: return getDrivingAgeSchoolChildC(); + case 18: return getPreDrivingAgeSchoolChildA(); + case 19: return getPreDrivingAgeSchoolChildB(); + case 20: return getPreDrivingAgeSchoolChildC(); + case 21: return getPreSchoolChildA(); + case 22: return getPreSchoolChildB(); + case 23: return getPreSchoolChildC(); + case 24: return getAgeA(); + case 25: return getFemaleA(); + case 26: return getMoreCarsThanWorkers(); + case 27: return getFewerCarsThanWorkers(); + case 28: return getIncomeLess20k(); + case 29: return getIncome50to100k(); + case 30: return getIncomeMore100k(); + case 31: return getUsualWorkLocationIsHome(); + case 32: return getNoUsualWorkLocation(); + case 33: return getNoUsualSchoolLocation(); + case 34: return getHhSize(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapCtrampApplication.java b/src/java/com/pb/cmap/tourBased/CmapCtrampApplication.java new file mode 100644 index 0000000..8f46de2 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapCtrampApplication.java @@ -0,0 +1,24 @@ + package com.pb.cmap.tourBased; + +import java.util.ResourceBundle; + + +import com.pb.common.util.ResourceUtil; +import com.pb.models.ctrampIf.jppf.CtrampApplication; + + + public class CmapCtrampApplication extends CtrampApplication{ + + public static final String PROGRAM_VERSION = "09June2008"; + public static final String PROPERTIES_PROJECT_DIRECTORY = "Project.Directory"; + + + + public CmapCtrampApplication( ResourceBundle rb ){ + super( rb ); + + projectDirectory = ResourceUtil.getProperty(rb, PROPERTIES_PROJECT_DIRECTORY); + + } + + } \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapCtrampDmuFactory.java b/src/java/com/pb/cmap/tourBased/CmapCtrampDmuFactory.java new file mode 100644 index 0000000..8a56218 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapCtrampDmuFactory.java @@ -0,0 +1,138 @@ +/* + * Copyright 2005 PB Consult Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.tourBased; + +import java.io.Serializable; + +import com.pb.models.ctrampIf.AtWorkSubtourFrequencyDMU; +import com.pb.models.ctrampIf.AutoOwnershipChoiceDMU; +import com.pb.models.ctrampIf.CoordinatedDailyActivityPatternDMU; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.FreeParkingChoiceDMU; +import com.pb.models.ctrampIf.IndividualMandatoryTourFrequencyDMU; +import com.pb.models.ctrampIf.IndividualNonMandatoryTourFrequencyDMU; +import com.pb.models.ctrampIf.JointTourFrequencyDMU; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ParkingChoiceDMU; +import com.pb.models.ctrampIf.StopDCSoaDMU; +import com.pb.models.ctrampIf.StopFrequencyDMU; +import com.pb.models.ctrampIf.StopLocationDMU; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourDepartureTimeAndDurationDMU; +import com.pb.models.ctrampIf.TripModeChoiceDMU; +import com.pb.cmap.tourBased.CmapModelStructure; + +/** + * ArcCtrampDmuFactory is a class that ... + * + * @author Kimberly Grommes + * @version 1.0, Jul 17, 2008 + * Created by IntelliJ IDEA. + */ +public class CmapCtrampDmuFactory implements CtrampDmuFactoryIf, Serializable { + + TazDataIf tazDataHandler; + CmapModelStructure modelStructure; + + public CmapCtrampDmuFactory( TazDataIf tazDataHandler, CmapModelStructure modelStructure ) { + this.tazDataHandler = tazDataHandler; + this.modelStructure = modelStructure; + } + + + + public AutoOwnershipChoiceDMU getAutoOwnershipDMU() { + return new CmapAutoOwnershipChoiceDMU(); + } + + + public FreeParkingChoiceDMU getFreeParkingChoiceDMU() { + return new CmapFreeParkingChoiceDMU(); + } + + + public CoordinatedDailyActivityPatternDMU getCoordinatedDailyActivityPatternDMU() { + return new CmapCoordinatedDailyActivityPatternDMU(); + } + + + public DcSoaDMU getDcSoaDMU() { + return new CmapDcSoaDMU( tazDataHandler ); + } + + + public DestChoiceDMU getDestChoiceDMU() { + return new CmapDestChoiceDMU( tazDataHandler, modelStructure ); + } + + + public TourModeChoiceDMU getModeChoiceDMU() { + return new CmapTourModeChoiceDMU( tazDataHandler, modelStructure ); + } + + + public IndividualMandatoryTourFrequencyDMU getIndividualMandatoryTourFrequencyDMU() { + return new CmapIndividualMandatoryTourFrequencyDMU(tazDataHandler); + } + + + public TourDepartureTimeAndDurationDMU getTourDepartureTimeAndDurationDMU() { + return new CmapTourDepartureTimeAndDurationDMU( tazDataHandler, modelStructure ); + } + + + public AtWorkSubtourFrequencyDMU getAtWorkSubtourFrequencyDMU() { + return new CmapAtWorkSubtourFrequencyDMU( modelStructure ); + } + + + public JointTourFrequencyDMU getJointTourFrequencyDMU() { + return new CmapJointTourFrequencyDMU( modelStructure ); + } + + + public IndividualNonMandatoryTourFrequencyDMU getIndividualNonMandatoryTourFrequencyDMU() { + return new CmapIndividualNonMandatoryTourFrequencyDMU(); + } + + + public StopFrequencyDMU getStopFrequencyDMU() { + return new CmapStopFrequencyDMU(tazDataHandler, modelStructure ); + } + + + public StopDCSoaDMU getStopDCSoaDMU() { + return new CmapStopDCSoaDMU(tazDataHandler, modelStructure); + } + + + public StopLocationDMU getStopLocationDMU() { + return new CmapStopLocationDMU(tazDataHandler, modelStructure); + } + + + public TripModeChoiceDMU getTripModeChoiceDMU() { + return new CmapTripModeChoiceDMU( tazDataHandler, modelStructure ); + } + + public ParkingChoiceDMU getParkingChoiceDMU() { + return new CmapParkingChoiceDMU( tazDataHandler, modelStructure ); + } + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapDcSoaDMU.java b/src/java/com/pb/cmap/tourBased/CmapDcSoaDMU.java new file mode 100644 index 0000000..1cc6c59 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapDcSoaDMU.java @@ -0,0 +1,195 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.TazDataIf; + + +public class CmapDcSoaDMU extends DcSoaDMU { + + TazDataIf tazDataManager; + + public CmapDcSoaDMU( TazDataIf tazDataManager ) { + super ( tazDataManager ); + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + } + + public double getOMazDMazDistanceAlt ( int alt ) { + int destZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), destZone); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getLnWorkOcc1DcSizeAlt", 0 ); + methodIndexMap.put( "getLnWorkOcc2DcSizeAlt", 1 ); + methodIndexMap.put( "getLnWorkOcc3DcSizeAlt", 2 ); + methodIndexMap.put( "getLnWorkOcc4DcSizeAlt", 3 ); + methodIndexMap.put( "getLnWorkOcc5DcSizeAlt", 4 ); + methodIndexMap.put( "getLnWorkOcc6DcSizeAlt", 5 ); + methodIndexMap.put( "getLnWorkOcc7DcSizeAlt", 6 ); + methodIndexMap.put( "getLnWorkOcc8DcSizeAlt", 7 ); + methodIndexMap.put( "getLnWorkOcc9DcSizeAlt", 8 ); + methodIndexMap.put( "getLnWorkOcc10DcSizeAlt", 9 ); + methodIndexMap.put( "getLnWorkOcc11DcSizeAlt", 10 ); + methodIndexMap.put( "getLnWorkOcc12DcSizeAlt", 11 ); + + methodIndexMap.put( "getLnUnivDcSizeAlt", 12 ); + methodIndexMap.put( "getLnSchoolPreDcSizeAlt", 13 ); + methodIndexMap.put( "getLnSchoolGradeDcSizeAlt", 14 ); + methodIndexMap.put( "getLnSchoolHighDcSizeAlt", 15 ); + methodIndexMap.put( "getLnEscortDcSizeAlt", 16 ); + methodIndexMap.put( "getLnShoppingDcSizeAlt", 17 ); + methodIndexMap.put( "getLnEatOutDcSizeAlt", 18 ); + methodIndexMap.put( "getLnOthMaintDcSizeAlt", 19 ); + methodIndexMap.put( "getLnSocialDcSizeAlt", 20 ); + methodIndexMap.put( "getLnOthDiscrDcSizeAlt", 21 ); + methodIndexMap.put( "getLnAtWorkDcSizeAlt", 22 ); + + methodIndexMap.put( "getWorkerOccupation", 23 ); + + methodIndexMap.put( "getOMazDMazDistanceAlt", 60 ); + } + + + // DMU methods - define one of these for every @var in the mode choice control file. + public double getLnWorkOcc1DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ1" ); + } + + public double getLnWorkOcc2DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ2" ); + } + + public double getLnWorkOcc3DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ3" ); + } + + public double getLnWorkOcc4DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ4" ); + } + + public double getLnWorkOcc5DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ5" ); + } + + public double getLnWorkOcc6DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ6" ); + } + + public double getLnWorkOcc7DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ7" ); + } + + public double getLnWorkOcc8DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ8" ); + } + + public double getLnWorkOcc9DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ9" ); + } + + public double getLnWorkOcc10DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ10" ); + } + + public double getLnWorkOcc11DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ11" ); + } + + public double getLnWorkOcc12DcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work_occ12" ); + } + + public double getLnUnivDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "university" ); + } + + public double getLnSchoolPreDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "school_pre" ); + } + + public double getLnSchoolGradeDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "school_grade" ); + } + + public double getLnSchoolHighDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "school_high" ); + } + + public double getLnEscortDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "escort" ); + } + + public double getLnShoppingDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "shop" ); + } + + public double getLnEatOutDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "eatingOut" ); + } + + public double getLnOthMaintDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "maintenance" ); + } + + public double getLnSocialDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "visiting" ); + } + + public double getLnOthDiscrDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "discretionary" ); + } + + public double getLnAtWorkDcSizeAlt( int alt ) { + return getLnDcSizeForPurpSegAlt( alt, "work-based" ); + } + + public int getWorkerOccupation() { + return person.getPersonWorkerOccupation(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getLnWorkOcc1DcSizeAlt( arrayIndex ); + case 1: return getLnWorkOcc2DcSizeAlt( arrayIndex ); + case 2: return getLnWorkOcc3DcSizeAlt( arrayIndex ); + case 3: return getLnWorkOcc4DcSizeAlt( arrayIndex ); + case 4: return getLnWorkOcc5DcSizeAlt( arrayIndex ); + case 5: return getLnWorkOcc6DcSizeAlt( arrayIndex ); + case 6: return getLnWorkOcc7DcSizeAlt( arrayIndex ); + case 7: return getLnWorkOcc8DcSizeAlt( arrayIndex ); + case 8: return getLnWorkOcc9DcSizeAlt( arrayIndex ); + case 9: return getLnWorkOcc10DcSizeAlt( arrayIndex ); + case 10: return getLnWorkOcc11DcSizeAlt( arrayIndex ); + case 11: return getLnWorkOcc12DcSizeAlt( arrayIndex ); + + case 12: return getLnUnivDcSizeAlt( arrayIndex ); + case 13: return getLnSchoolPreDcSizeAlt( arrayIndex ); + case 14: return getLnSchoolGradeDcSizeAlt( arrayIndex ); + case 15: return getLnSchoolHighDcSizeAlt( arrayIndex ); + case 16: return getLnEscortDcSizeAlt( arrayIndex ); + case 17: return getLnShoppingDcSizeAlt( arrayIndex ); + case 18: return getLnEatOutDcSizeAlt( arrayIndex ); + case 19: return getLnOthMaintDcSizeAlt( arrayIndex ); + case 20: return getLnSocialDcSizeAlt( arrayIndex ); + case 21: return getLnOthDiscrDcSizeAlt( arrayIndex ); + case 22: return getLnAtWorkDcSizeAlt( arrayIndex ); + + case 23: return getWorkerOccupation( ); + + case 60: return getOMazDMazDistanceAlt( arrayIndex ); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapDestChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapDestChoiceDMU.java new file mode 100644 index 0000000..6fe60b2 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapDestChoiceDMU.java @@ -0,0 +1,312 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; + + +public class CmapDestChoiceDMU extends DestChoiceDMU { + + private int[] zoneTableRow; + private int[] areaType; + private int[] district; + private int[] county; + private int[] gradeschool; + private int[] highschool; + + private int workLogsumIndex; + private int schoolLogsumIndex; + private int nonManLogsumIndex; + + TazDataIf tazDataManager; + + public CmapDestChoiceDMU( TazDataIf tazDataManager, ModelStructure modelStructure ) { + super( tazDataManager, modelStructure ); + setup( tazDataManager ); + setupMethodIndexMap(); + } + + private void setup( TazDataIf tazDataManager) { + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned us 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + district = tazDataManager.getZonalDistrict(); + county = tazDataManager.getZonalCounty(); + gradeschool = tazDataManager.getZonalHighSchool(); + highschool = tazDataManager.getZonalGradeSchool(); + + workLogsumIndex = modelStructure.getPeriodCombinationIndex( modelStructure.getWorkLocationDefaultDepartPeriod(), modelStructure.getWorkLocationDefaultArrivePeriod() ); + schoolLogsumIndex = modelStructure.getPeriodCombinationIndex( modelStructure.getSchoolLocationDefaultDepartPeriod(), modelStructure.getSchoolLocationDefaultArrivePeriod() ); + nonManLogsumIndex = modelStructure.getPeriodCombinationIndex( modelStructure.getNonMandatoryLocationDefaultDepartPeriod(), modelStructure.getNonMandatoryLocationDefaultArrivePeriod() ); + + this.tazDataManager = tazDataManager; + } + + + protected int getIncome() { + return hh.getIncomeSegment(); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getOrigAreaType", 0 ); + methodIndexMap.put( "getOrigDistrict", 1 ); + methodIndexMap.put( "getOriginCounty", 2 ); + methodIndexMap.put( "getDestAreaTypeAlt", 3 ); + methodIndexMap.put( "getDestDistrictAlt", 4 ); + methodIndexMap.put( "getDestCountyAlt", 5 ); + + methodIndexMap.put( "getLnWorkOcc1DcSizeAlt", 6 ); + methodIndexMap.put( "getLnWorkOcc2DcSizeAlt", 7 ); + methodIndexMap.put( "getLnWorkOcc3DcSizeAlt", 8 ); + methodIndexMap.put( "getLnWorkOcc4DcSizeAlt", 9 ); + methodIndexMap.put( "getLnWorkOcc5DcSizeAlt", 10 ); + methodIndexMap.put( "getLnWorkOcc6DcSizeAlt", 11 ); + methodIndexMap.put( "getLnWorkOcc7DcSizeAlt", 12 ); + methodIndexMap.put( "getLnWorkOcc8DcSizeAlt", 13 ); + methodIndexMap.put( "getLnWorkOcc9DcSizeAlt", 14 ); + methodIndexMap.put( "getLnWorkOcc10DcSizeAlt", 15 ); + methodIndexMap.put( "getLnWorkOcc11DcSizeAlt", 16); + methodIndexMap.put( "getLnWorkOcc12DcSizeAlt", 17 ); + + methodIndexMap.put( "getLnUnivDcSizeAlt", 18 ); + methodIndexMap.put( "getLnSchoolPreDcSizeAlt", 19 ); + methodIndexMap.put( "getLnSchoolGradeDcSizeAlt", 20 ); + methodIndexMap.put( "getLnSchoolHighDcSizeAlt", 21 ); + methodIndexMap.put( "getLnEscortDcSizeAlt", 22 ); + methodIndexMap.put( "getLnShoppingDcSizeAlt", 23 ); + methodIndexMap.put( "getLnEatOutDcSizeAlt", 24 ); + methodIndexMap.put( "getLnOthMaintDcSizeAlt", 25 ); + methodIndexMap.put( "getLnSocialDcSizeAlt", 26 ); + methodIndexMap.put( "getLnOthDiscrDcSizeAlt", 27 ); + methodIndexMap.put( "getLnAtWorkDcSizeAlt", 28 ); + methodIndexMap.put( "getPersonIsFullTimeWorker", 29 ); + methodIndexMap.put( "getSubtourType", 30 ); + methodIndexMap.put( "getDcSoaCorrectionsAlt", 31 ); + methodIndexMap.put( "getWorkLocationMcLogsumAlt", 32 ); + methodIndexMap.put( "getSchoolLocationMcLogsumAlt", 33 ); + methodIndexMap.put( "getNonMandatoryLocationMcLogsumAlt", 34 ); + methodIndexMap.put( "getZonalShortWalkAccessOrig", 35 ); + methodIndexMap.put( "getZonalShortWalkAccessDestAlt", 36 ); + methodIndexMap.put( "getIncome", 37 ); + methodIndexMap.put( "getAutos", 38 ); + methodIndexMap.put( "getWorkers", 39 ); + methodIndexMap.put( "getNumChildrenUnder16", 40 ); + methodIndexMap.put( "getNumChildrenUnder19", 41 ); + methodIndexMap.put( "getAge", 42 ); + methodIndexMap.put( "getFullTimeWorker", 43 ); + methodIndexMap.put( "getWorkTaz", 44 ); + methodIndexMap.put( "getWorkTourModeIsSOV", 45 ); + methodIndexMap.put( "getTourIsJoint", 46 ); + methodIndexMap.put( "getHighestEducationAttainment", 47 ); + methodIndexMap.put( "getWorkerOccupation", 48 ); + + methodIndexMap.put( "getOriginGradeSchool", 49 ); + methodIndexMap.put( "getOriginHighSchool", 50 ); + methodIndexMap.put( "getDestGradeSchoolAlt", 51 ); + methodIndexMap.put( "getDestHighSchoolAlt", 52 ); + methodIndexMap.put( "getPersonIsFemale", 53 ); + methodIndexMap.put( "getPersonIsPartTimeWorker", 54 ); + methodIndexMap.put( "getNumberOfNonWorkingAdults", 55 ); + methodIndexMap.put( "getNumRetired", 56 ); + + methodIndexMap.put( "getOMazDMazDistanceAlt", 60 ); + + + } + + public void setMcLogsum( int index, int zone, int subzone, double logsum ){ + modeChoiceLogsums[index][zone][subzone] = logsum; + } + + + public double getWorkLocationMcLogsumAlt ( int alt ) { + int zone = altToZone[alt]; + int subZone = altToSubZone[alt]; + return getMcLogsumDestAlt( workLogsumIndex, zone, subZone ); + } + + public double getSchoolLocationMcLogsumAlt ( int alt ) { + int zone = altToZone[alt]; + int subZone = altToSubZone[alt]; + return getMcLogsumDestAlt( schoolLogsumIndex, zone, subZone ); + } + + public double getNonMandatoryLocationMcLogsumAlt ( int alt ) { + int zone = altToZone[alt]; + int subZone = altToSubZone[alt]; + return getMcLogsumDestAlt( nonManLogsumIndex, zone, subZone ); + } + + + public int getOrigAreaType() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return areaType[index]; + } + + public int getOrigDistrict() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return district[index]; + } + + public int getOriginCounty() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return county[index]; + } + + public int getOriginGradeSchool() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return gradeschool[index]; + } + + public int getOriginHighSchool() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return highschool[index]; + } + + public int getDestAreaTypeAlt( int alt ) { + int destZone = altToZone[alt]; + int index = zoneTableRow[destZone] - 1; + return areaType[index]; + } + + public int getDestDistrictAlt( int alt ) { + int destZone = altToZone[alt]; + int index = zoneTableRow[destZone] - 1; + return district[index]; + } + + public int getDestCountyAlt( int alt ) { + int destZone = altToZone[alt]; + int index = zoneTableRow[destZone] - 1; + return county[index]; + } + + public int getDestGradeSchoolAlt( int alt ) { + int destZone = altToZone[alt]; + int index = zoneTableRow[destZone] - 1; + return gradeschool[index]; + } + + public int getDestHighSchoolAlt( int alt ) { + int destZone = altToZone[alt]; + int index = zoneTableRow[destZone] - 1; + return highschool[index]; + } + + public int getPersonIsFullTimeWorker() { + return person.getPersonIsFullTimeWorker(); + } + + public int getPersonIsPartTimeWorker() { + return person.getPersonIsPartTimeWorker(); + } + + public int getSubtourType() { + if ( tour.getTourCategoryIsAtWork() ) + return tour.getTourPrimaryPurposeIndex(); + else + return 0; + } + + public int getHighestEducationAttainment() { + return hh.getHighestEducationAttainment(); + } + + public int getWorkerOccupation() { + return person.getPersonWorkerOccupation(); + } + + public int getNumberOfNonWorkingAdults() { + return hh.getNumberOfNonWorkingAdults(); + } + + public int getNumRetired() { + return hh.getNumRetired(); + } + + public double getOMazDMazDistanceAlt ( int alt ) { + int destZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), destZone); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getOrigAreaType(); + case 1: return getOrigDistrict(); + case 2: return getOriginCounty(); + case 3: return getDestAreaTypeAlt( arrayIndex ); + case 4: return getDestDistrictAlt( arrayIndex ); + case 5: return getDestCountyAlt( arrayIndex ); + + case 6: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ1" ); + case 7: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ2" ); + case 8: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ3" ); + case 9: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ4" ); + case 10: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ5" ); + case 11: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ6" ); + case 12: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ7" ); + case 13: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ8" ); + case 14: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ9" ); + case 15: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ10" ); + case 16: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ11" ); + case 17: return getLnDcSizeForPurposeAlt( arrayIndex, "work_occ12" ); + + case 18: return getLnDcSizeForPurposeAlt( arrayIndex, "university" ); + case 19: return getLnDcSizeForPurposeAlt( arrayIndex, "school_pre" ); + case 20: return getLnDcSizeForPurposeAlt( arrayIndex, "school_grade" ); + case 21: return getLnDcSizeForPurposeAlt( arrayIndex, "school_high" ); + case 22: return getLnDcSizeForPurposeAlt( arrayIndex, "escort" ); + case 23: return getLnDcSizeForPurposeAlt( arrayIndex, "shop" ); + case 24: return getLnDcSizeForPurposeAlt( arrayIndex, "eatingOut" ); + case 25: return getLnDcSizeForPurposeAlt( arrayIndex, "maintenance" ); + case 26: return getLnDcSizeForPurposeAlt( arrayIndex, "visiting" ); + case 27: return getLnDcSizeForPurposeAlt( arrayIndex, "discretionary" ); + case 28: return getLnDcSizeForPurposeAlt( arrayIndex, "work-based" ); + case 29: return getPersonIsFullTimeWorker(); + case 30: return getSubtourType(); + case 31: return getDcSoaCorrectionsAlt( arrayIndex ); + case 32: return getWorkLocationMcLogsumAlt( arrayIndex ); + case 33: return getSchoolLocationMcLogsumAlt( arrayIndex ); + case 34: return getNonMandatoryLocationMcLogsumAlt( arrayIndex ); + case 35: return getZonalShortWalkAccessOrig(); + case 36: return getZonalShortWalkAccessDestAlt( arrayIndex ); + case 37: return getIncome(); + case 38: return getAutos(); + case 39: return getWorkers(); + case 40: return getNumChildrenUnder16(); + case 41: return getNumChildrenUnder19(); + case 42: return getAge(); + case 43: return getFullTimeWorker(); + case 44: return getWorkTaz(); + case 45: return getWorkTourModeIsSOV(); + case 46: return getTourIsJoint(); + case 47: return getHighestEducationAttainment(); + case 48: return getWorkerOccupation(); + + case 49: return getOriginGradeSchool(); + case 50: return getOriginHighSchool(); + case 51: return getDestGradeSchoolAlt( arrayIndex ); + case 52: return getDestHighSchoolAlt( arrayIndex ); + case 53: return getPersonIsFemale(); + case 54: return getPersonIsPartTimeWorker(); + case 55: return getNumberOfNonWorkingAdults(); + case 56: return getNumRetired(); + + case 60: return getOMazDMazDistanceAlt( arrayIndex ); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapFreeParkingChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapFreeParkingChoiceDMU.java new file mode 100644 index 0000000..6a72d10 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapFreeParkingChoiceDMU.java @@ -0,0 +1,52 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.FreeParkingChoiceDMU; + + +public class CmapFreeParkingChoiceDMU extends FreeParkingChoiceDMU { + + + + public CmapFreeParkingChoiceDMU() { + super(); + setupMethodIndexMap(); + } + + + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getHHIncome", 0 ); + methodIndexMap.put( "getAutoOwnership", 1 ); + methodIndexMap.put( "getFtwkPersons", 2 ); + methodIndexMap.put( "getPtwkPersons", 3 ); + methodIndexMap.put( "getSize", 4 ); + } + + + + public int getHHIncome() { + return hh.getIncomeSegment(); + } + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getHHIncome(); + case 1: return getAutoOwnership(); + case 2: return getFtwkPersons(); + case 3: return getPtwkPersons(); + case 4: return getSize(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapHouseholdDataManager.java b/src/java/com/pb/cmap/tourBased/CmapHouseholdDataManager.java new file mode 100644 index 0000000..6a2604d --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapHouseholdDataManager.java @@ -0,0 +1,466 @@ +package com.pb.cmap.tourBased; + +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.cmap.ctramp.Person; +import com.pb.cmap.ctramp.Household; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.HouseholdDataManager; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import gnu.cajo.invoke.Remote; +import gnu.cajo.utils.ItemServer; + +/** + * @author Jim Hicks + * + * Class for managing household and person object data read from synthetic population files. + */ +public class CmapHouseholdDataManager extends HouseholdDataManager { + + public static final String HH_DATA_SERVER_NAME = CmapHouseholdDataManager.class.getCanonicalName(); + public static final String HH_DATA_SERVER_ADDRESS = "127.0.0.1"; + public static final int HH_DATA_SERVER_PORT = 1139; + + + + + public CmapHouseholdDataManager() { + super (); + } + + + + + // this method gets called by ArcTourBasedModel, if the HouseholdDataManagerIf instance is and ArcHouseholdDataManager object. + public void mapTablesToHouseholdObjects( String inputHouseholdFileName, String inputPersonFileName, ModelStructure modelStructure, TazDataIf tazDataManager ) { + setupHouseholdDataManager( modelStructure, tazDataManager, inputHouseholdFileName, inputPersonFileName ); + } + + + /** + * Associate data in hh and person TableDataSets read from synthetic population files with + * Household objects and Person objects with Households. + * + */ + public void mapTablesToHouseholdObjects() { + + logger.info( "mapping popsyn household and person data records to objects." ); + + //read in worker occupation codes mapping + try { + readWorkerOccupationFile(); + } catch (Exception e) { + logger.fatal( String.format("exception reading worker occupation code mapping")); + throw new RuntimeException(e); + } + + int id = -1; + int invalidPersonTypeCount = 0; + + // get the maximum HH id value to use to dimension the hhIndex correspondence array. + // the hhIndex array will store the hhArray index number for the given hh index. + int maxHhId = 0; + for ( int r=1; r <= hhTable.getRowCount(); r++ ) { + id = (int)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_ID_FIELD_NAME ) ); + if ( id > maxHhId ) + maxHhId = id; + } + hhIndexArray = new int[maxHhId+1]; + + + // get an index array for households sorted in random order + int[] randomSortedIndices = getRandomOrderHhIndexArray( hhTable.getRowCount() ); + + + fullHhArray = null; + + int numHouseholdsInSample = (int)( hhTable.getRowCount() * sampleRate ); + HouseholdIf[] hhArray = new HouseholdIf[numHouseholdsInSample]; + + int[] hhTazSortArray = new int[numHouseholdsInSample]; + for ( int i=0; i < numHouseholdsInSample; i++ ) { + int r = randomSortedIndices[i] + 1; + int htaz = (int)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_HOME_TAZ_FIELD_NAME ) ); + hhTazSortArray[i] = htaz; + } + + // get an index array for households sorted in order of home taz + int[] newOrder = new int[numHouseholdsInSample]; + int[] sortedIndices = getHomeTazOrderHhIndexArray( hhTazSortArray ); + for ( int i=0; i < sortedIndices.length; i++ ) { + int k = sortedIndices[i]; + newOrder[k] = i; + } + + + + + // for each household in the sample + for ( int i=0; i < numHouseholdsInSample; i++ ) { + + int r = randomSortedIndices[i] + 1; + + try { + + // create a Household object + HouseholdIf hh = new Household( modelStructure ); + + // get required values from table record and store in Household object + id = (int)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_ID_FIELD_NAME ) ); + hh.setHhId ( id, inputRandomSeed ); + + // set the household in the hhIndexArray in random order + //int index = sortedIndices[r-1]; + int newIndex = newOrder[i]; + hhIndexArray[hh.getHhId()] = newIndex; + + short htaz = (short)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_HOME_TAZ_FIELD_NAME ) ); + hh.setHhTaz ( htaz ); + + double rn = hh.getHhRandom().nextDouble(); + short origWalkSubzone = getInitialOriginWalkSegment ( htaz, rn ); + hh.setHhWalkSubzone(origWalkSubzone); + + // autos could be modeled or from PUMA + short numAutos = (short)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_AUTOS_FIELD_NAME ) ); + hh.setHhAutos ( numAutos ); + + // set the hhSize variable and create Person objects for each person + short numPersons = (short)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_SIZE_FIELD_NAME ) ); + hh.setHhSize ( numPersons ); + + short numWorkers = (short)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_WORKERS_FIELD_NAME ) ); + hh.setHhWorkers ( numWorkers ); + + int incomeInDollars = (int)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_INCOME_DOLLARS_FIELD_NAME )); + hh.setHhIncomeInDollars ( incomeInDollars ); + + short type = (short)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_TYPE_FIELD_NAME )); + hh.setHhType( type ); + + int bldgsz = (int) hhTable.getValueAt(r, hhTable.getColumnPosition(HH_BLDGSZ_FIELD_NAME)); + hh.setHhBldgsz(bldgsz); + + hh.initializeWindows(); + hhArray[newIndex] = hh; + + } + catch (Exception e) { + + logger.fatal( String.format( "exception caught mapping household data record to a Household object, r=%d, id=%d.", r, id) ); + throw new RuntimeException(e); + + } + + } + + + + int[] personHhStart = new int[maxHhId+1]; + int[] personHhEnd = new int[maxHhId+1]; + + // get hhid for person record 1 + int hhid = (int)personTable.getValueAt( 1, personTable.getColumnPosition( PERSON_HH_ID_FIELD_NAME ) ); + personHhStart[hhid] = 1; + int oldHhid = hhid; + + for ( int r=1; r <= personTable.getRowCount(); r++ ) { + + // get the Household object for this person data to be stored in + hhid = (int)personTable.getValueAt( r, personTable.getColumnPosition( PERSON_HH_ID_FIELD_NAME ) ); + + if ( hhid > oldHhid ) { + personHhEnd[oldHhid] = r-1; + oldHhid = hhid; + personHhStart[hhid] = r; + } + + } + personHhEnd[hhid] = personTable.getRowCount(); + + + for ( int i=0; i < numHouseholdsInSample; i++ ) { + + int r = randomSortedIndices[i] + 1; + + hhid = (int)hhTable.getValueAt( r, hhTable.getColumnPosition( HH_ID_FIELD_NAME ) ); + + int index = hhIndexArray[hhid]; + HouseholdIf hh = hhArray[index]; + + int persNum = 1; + for ( int p=personHhStart[hhid]; p <= personHhEnd[hhid]; p++ ) { + + // get the Person object for this person data to be stored in + int persId = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_PERSON_ID_FIELD_NAME ) ); + PersonIf person = hh.getPerson ( persNum++ ); + person.setPersId( persId ); + + // get required values from table record and store in Person object + int age = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_AGE_FIELD_NAME ) ); + person.setPersAge ( age ); + + int gender = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_GENDER_FIELD_NAME ) ); + person.setPersGender ( gender ); + + // Employment status (1-employed FT, 2-employed PT, 3-not employed, 4-under age 16) + int empCat = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_EMPLOYMENT_CATEGORY_FIELD_NAME ) ); + person.setPersEmploymentCategory ( empCat ); + + // Student status (1 - student in grade or high school; 2 - student in college or higher; 3 - not a student) + int studentCat = (int)personTable.getValueAt( p, personTable.getColumnPosition(PERSON_STUDENT_CATEGORY_FIELD_NAME)); + person.setPersStudentCategory(studentCat); + + // Person type (1-FT worker age 16+, 2-PT worker nonstudent age 16+, 3-university student, 4-nonworker nonstudent age 16-64, + // 5-nonworker nonstudent age 65+, 6-"age 16-19 student, not FT wrkr or univ stud", 7-age 6-15 schpred, 8 under age 6 presch + int personType = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_TYPE_CATEGORY_FIELD_NAME ) ); + person.setPersonTypeCategory ( personType ); + + // Person education attainment - PUMS EDUC attribute + int personEduc = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_EDUC_CATEGORY_FIELD_NAME ) ); + person.setPersonEducAttainment( personEduc ); + + // Person census industry - PUMS INDCEN attribute + int personIndCen = (int)personTable.getValueAt( p, personTable.getColumnPosition( PERSON_INDCEN_CATEGORY_FIELD_NAME ) ); + person.setPersonIndustryCensus( personIndCen ); + + // Person worker occupation + person.setPersonWorkerOccupation(getPersonWorkOccupation(personIndCen)); + + // if person is a university student but has school age student category value, reset student category value + if ( personType == Person.PersonType.University_student.ordinal() && studentCat != Person.StudentStatus.STUDENT_COLLEGE_OR_HIGHER.ordinal() ) { + studentCat = Person.StudentStatus.STUDENT_COLLEGE_OR_HIGHER.ordinal(); + person.setPersStudentCategory( studentCat ); + invalidPersonTypeCount++; + } + // if person is a student of any kind but has full-time employment status, reset student category value to non-student + else if ( studentCat != Person.StudentStatus.NON_STUDENT.ordinal() && empCat == Person.EmployStatus.FULL_TIME.ordinal() ) { + studentCat = Person.StudentStatus.NON_STUDENT.ordinal(); + person.setPersStudentCategory( studentCat ); + invalidPersonTypeCount++; + } + + + // check consistency of student category and person type + if ( studentCat == Person.StudentStatus.NON_STUDENT.ordinal() ) { + + if ( person.getPersonIsStudentNonDriving() == 1 || person.getPersonIsStudentDriving() == 1 ) { + studentCat = Person.StudentStatus.STUDENT_HIGH_SCHOOL_OR_LESS.ordinal(); + person.setPersStudentCategory( studentCat ); + invalidPersonTypeCount++; + } + + } + + + // set usual work and school location choice segments + if ( personType == Person.EmployStatus.FULL_TIME.ordinal() || personType == Person.EmployStatus.PART_TIME.ordinal() ) { + String purposeName = modelStructure.getWorkPurposeFromOccupation( person.getPersonWorkerOccupation() ); + int purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + person.setWorkLocationPurposeIndex( purposeIndex ); + } + else if ( studentCat == Person.StudentStatus.STUDENT_COLLEGE_OR_HIGHER.ordinal() ) { + String purposeName = modelStructure.getUniversityPurpose(); + int purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + person.setUniversityLocationPurposeIndex( purposeIndex ); + + // set work purpose if part-time worker + if ( empCat == 2 ) { + purposeName = modelStructure.getWorkPurposeFromOccupation( person.getPersonWorkerOccupation() ); + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + person.setWorkLocationPurposeIndex( purposeIndex ); + } + } + else if ( person.getPersonIsPreschoolChild() == 1 || studentCat == Person.StudentStatus.STUDENT_HIGH_SCHOOL_OR_LESS.ordinal() ) { + String purposeName = modelStructure.getSchoolPurpose( person.getAge() ); + int purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + person.setSchoolLocationPurposeIndex( purposeIndex ); + + // set work purpose if part-time worker + if ( empCat == 2 ) { + purposeName = modelStructure.getWorkPurposeFromOccupation( person.getPersonWorkerOccupation() ); + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + person.setWorkLocationPurposeIndex( purposeIndex ); + } + } + + } + + } + + + fullHhArray = hhArray; + + logger.warn ( invalidPersonTypeCount + " person records had their type changed."); + + //set person value-of-time + logger.info("Setting distributed values of time. "); + setDistributedValuesOfTime(); + + logger.info("Setting distributed person walk preferences. "); + try { + setDistributedWalkPrefernces(); + } catch (Exception e) { + logger.fatal( String.format("exception reading person walk preferences file")); + throw new RuntimeException(e); + } + + //set person user class + logger.info("Setting person user class. "); + setUserClass(); + + } + + + + + /** + * if called, must be called after readData so that the size of the full population is known. + * @param hhFileName + * @param persFileName + * @param numHhs + */ + public void createSamplePopulationFiles ( String hhFileName, String persFileName, String newHhFileName, String newPersFileName, int numHhs ) { + + int maximumHhId = 0; + for( int i=0; i< fullHhArray.length; i++ ){ + int id = fullHhArray[i].getHhId(); + if( id > maximumHhId ) + maximumHhId = id; + } + + int[] testHhs = new int[maximumHhId+1]; + + int[] sortedIndices = getRandomOrderHhIndexArray( fullHhArray.length ); + + for ( int i=0; i < numHhs; i++) { + int k = sortedIndices[i]; + int hhId = fullHhArray[k].getHhId(); + testHhs[hhId] = 1; + } + + + String hString = ""; + int hCount = 0; + try { + + logger.info( String.format( "writing sample household file for %d households", numHhs ) ); + + PrintWriter out = new PrintWriter ( new BufferedWriter( new FileWriter(newHhFileName) ) ) ; + BufferedReader in = new BufferedReader( new FileReader(hhFileName) ); + + // read headers and write to output files + hString = in.readLine(); + out.write( hString + "\n" ); + hCount++; + int count = 0; + + while ( ( hString = in.readLine() ) != null ) { + hCount++; + int endOfField = hString.indexOf(','); + int hhId = Integer.parseInt( hString.substring(0, endOfField) ); + + // if it's a sample hh, write the hh and the person records + if ( testHhs[hhId] == 1 ) { + out.write( hString + "\n" ); + count++; + if ( count == numHhs ) + break; + } + } + + out.close(); + + } + catch (IOException e) { + logger.fatal ("IO Exception caught creating sample synpop household file."); + logger.fatal (String.format("reading hh file = %s, writing sample hh file = %s.", hhFileName, newHhFileName) ); + logger.fatal (String.format("hString = %s, hCount = %d.", hString, hCount) ); + } + + + String pString = ""; + int pCount = 0; + try { + + logger.info( String.format( "writing sample person file for selected households" ) ); + + PrintWriter out = new PrintWriter ( new BufferedWriter ( new FileWriter (newPersFileName) ) ) ; + BufferedReader in = new BufferedReader( new FileReader(persFileName) ); + + // read headers and write to output files + pString = in.readLine(); + out.write( pString + "\n" ); + pCount++; + int count = 0; + int oldId = 0; + while ( ( pString = in.readLine() ) != null ) { + pCount++; + int endOfField = pString.indexOf(','); + int hhId = Integer.parseInt( pString.substring(0, endOfField) ); + + // if it's a sample hh, write the hh and the person records + if ( testHhs[hhId] == 1 ) { + out.write( pString + "\n" ); + if ( hhId > oldId ) + count++; + } + else { + if ( count == numHhs ) + break; + } + + oldId = hhId; + + } + + out.close(); + + } + catch (IOException e) { + logger.fatal ("IO Exception caught creating sample synpop person file."); + logger.fatal (String.format("reading person file = %s, writing sample person file = %s.", persFileName, newPersFileName) ); + logger.fatal (String.format("pString = %s, pCount = %d.", pString, pCount) ); + } + + + } + + + public static void main(String args[]) throws Exception { + + String serverAddress = HH_DATA_SERVER_ADDRESS; + int serverPort = HH_DATA_SERVER_PORT; + + + // optional arguments + for (int i=0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("-hostname")) { + serverAddress = args[i+1]; + } + + if (args[i].equalsIgnoreCase("-port")) { + serverPort = Integer.parseInt( args[i+1] ); + } + } + + Remote.config( serverAddress, serverPort, null, 0 ); + + CmapHouseholdDataManager hhDataManager = new CmapHouseholdDataManager(); + + ItemServer.bind( hhDataManager, HH_DATA_SERVER_NAME ); + + System.out.println( String.format("CmapHouseholdDataManager server class started on: %s:%d", serverAddress, serverPort ) ); + + } + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapIndividualMandatoryTourFrequencyDMU.java b/src/java/com/pb/cmap/tourBased/CmapIndividualMandatoryTourFrequencyDMU.java new file mode 100644 index 0000000..00dde82 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapIndividualMandatoryTourFrequencyDMU.java @@ -0,0 +1,163 @@ +/* + * Copyright 2005 PB Consult Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.IndividualMandatoryTourFrequencyDMU; +import com.pb.models.ctrampIf.TazDataIf; + +/** + * ArcIndividualMandatoryTourFrequencyDMU is a class that ... + * + * @author Kimberly Grommes + * @version 1.0, Jul 17, 2008 + * Created by IntelliJ IDEA. + */ +public class CmapIndividualMandatoryTourFrequencyDMU extends IndividualMandatoryTourFrequencyDMU { + + TazDataIf tazDataManager; + + public CmapIndividualMandatoryTourFrequencyDMU(TazDataIf tazDataManager){ + super(); + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + } + + + public int getIncomeHigherThan50k(){ + if(household.getIncomeSegment()>2) return (1); + return(0); + } + + public int getOmazOtaz() { + return(tazDataManager.getTazsForMazs()[dmuIndex.getOriginZone()-1]); + } + + public int getDmazDtazUsualWorkLocation() { + int workZone = person.getUsualWorkLocation(); + if(workZone>0) { + return(tazDataManager.getTazsForMazs()[person.getUsualWorkLocation()-1]); + } else { + return 0; + } + } + + public int getDmazDtazUsualSchoolLocation() { + int schoolZone = person.getUsualSchoolLocation(); + if(schoolZone>0) { + return(tazDataManager.getTazsForMazs()[person.getUsualSchoolLocation()-1]); + } else { + return 0; + } + } + + public float getOMazDMazDistanceUsualWorkLocation() { + int workZone = person.getUsualWorkLocation(); + if(workZone>0) { + return(tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), workZone)); + } else { + return 9999; + } + } + + public float getOMazDMazDistanceUsualSchoolLocation() { + int schoolZone = person.getUsualSchoolLocation(); + if(schoolZone>0) { + return(tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), schoolZone)); + } else { + return 9999; + } + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getFullTimeWorker", 0 ); + methodIndexMap.put( "getPartTimeWorker", 1 ); + methodIndexMap.put( "getUniversityStudent", 2 ); + methodIndexMap.put( "getNonWorkingAdult", 3 ); + methodIndexMap.put( "getRetired", 4 ); + methodIndexMap.put( "getDrivingAgeSchoolChild", 5 ); + methodIndexMap.put( "getPreDrivingAgeSchoolChild", 6 ); + methodIndexMap.put( "getFemale", 7 ); + methodIndexMap.put( "getAge", 8 ); + methodIndexMap.put( "getStudentIsEmployed", 9 ); + methodIndexMap.put( "getNonStudentGoesToSchool", 10 ); + methodIndexMap.put( "getAutos", 11 ); + methodIndexMap.put( "getDrivers", 12 ); + methodIndexMap.put( "getPreschoolChildren", 13 ); + methodIndexMap.put( "getNonWorkers", 14 ); + methodIndexMap.put( "getIncomeHigherThan50k", 15 ); + methodIndexMap.put( "getNonFamilyHousehold", 16 ); + methodIndexMap.put( "getChildrenUnder16NotAtSchool", 17 ); + methodIndexMap.put( "getAreaType", 18 ); + methodIndexMap.put( "getUsualWorkLocation", 19 ); + methodIndexMap.put( "getUsualSchoolLocation", 20 ); + + methodIndexMap.put( "getOmazOtaz", 30 ); + methodIndexMap.put( "getDmazDtazUsualWorkLocation", 31 ); + methodIndexMap.put( "getDmazDtazUsualSchoolLocation", 32 ); + methodIndexMap.put( "getOMazDMazDistanceUsualWorkLocation", 33 ); + methodIndexMap.put( "getOMazDMazDistanceUsualSchoolLocation", 34 ); + + } + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getFullTimeWorker(); + case 1: return getPartTimeWorker(); + case 2: return getUniversityStudent(); + case 3: return getNonWorkingAdult(); + case 4: return getRetired(); + case 5: return getDrivingAgeSchoolChild(); + case 6: return getPreDrivingAgeSchoolChild(); + case 7: return getFemale(); + case 8: return getAge(); + case 9: return getStudentIsEmployed(); + case 10: return getNonStudentGoesToSchool(); + case 11: return getAutos(); + case 12: return getDrivers(); + case 13: return getPreschoolChildren(); + case 14: return getNonWorkers(); + case 15: return getIncomeHigherThan50k(); + case 16: return getNonFamilyHousehold(); + case 17: return getChildrenUnder16NotAtSchool(); + case 18: return getAreaType(); + case 19: return getUsualWorkLocation(); + case 20: return getUsualSchoolLocation(); + + case 30: return getOmazOtaz(); + case 31: return getDmazDtazUsualWorkLocation(); + case 32: return getDmazDtazUsualSchoolLocation(); + case 33: return getOMazDMazDistanceUsualWorkLocation(); + case 34: return getOMazDMazDistanceUsualSchoolLocation(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapIndividualNonMandatoryTourFrequencyDMU.java b/src/java/com/pb/cmap/tourBased/CmapIndividualNonMandatoryTourFrequencyDMU.java new file mode 100644 index 0000000..d601cfc --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapIndividualNonMandatoryTourFrequencyDMU.java @@ -0,0 +1,165 @@ +/* + * Copyright 2005 PB Consult Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.IndividualNonMandatoryTourFrequencyDMU; + + +/** + * ArcIndividualNonMandatoryTourFrequencyDMU is a class that ... + * + */ +public class CmapIndividualNonMandatoryTourFrequencyDMU extends IndividualNonMandatoryTourFrequencyDMU { + + + public CmapIndividualNonMandatoryTourFrequencyDMU(){ + super(); + setupMethodIndexMap(); + } + + + + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getIncomeInDollars", 0 ); + methodIndexMap.put( "getHouseholdSize", 1 ); + methodIndexMap.put( "getNumAutos", 2 ); + methodIndexMap.put( "getCarsEqualsWorkers", 3 ); + methodIndexMap.put( "getMoreCarsThanWorkers", 4 ); + methodIndexMap.put( "getNumAdults", 5 ); + methodIndexMap.put( "getNumChildren", 6 ); + methodIndexMap.put( "getPersonIsAdult", 7 ); + methodIndexMap.put( "getPersonIsChild", 8 ); + methodIndexMap.put( "getPersonIsFullTimeWorker", 9 ); + methodIndexMap.put( "getPersonIsPartTimeWorker", 10 ); + methodIndexMap.put( "getPersonIsUniversity", 11 ); + methodIndexMap.put( "getPersonIsNonworker", 12 ); + methodIndexMap.put( "getPersonIsPreschool", 13 ); + methodIndexMap.put( "getPersonIsStudentNonDriving", 14 ); + methodIndexMap.put( "getPersonIsStudentDriving", 15 ); + methodIndexMap.put( "getPersonStaysHome", 16 ); + methodIndexMap.put( "getFemale", 17 ); + methodIndexMap.put( "getFullTimeWorkers", 18 ); + methodIndexMap.put( "getPartTimeWorkers", 19 ); + methodIndexMap.put( "getUniversityStudents", 20 ); + methodIndexMap.put( "getNonWorkers", 21 ); + methodIndexMap.put( "getDrivingAgeStudents", 22 ); + methodIndexMap.put( "getNonDrivingAgeStudents", 23 ); + methodIndexMap.put( "getPreSchoolers", 24 ); + methodIndexMap.put( "getHomeTazIsUrban", 25 ); + methodIndexMap.put( "getMaxAdultOverlaps", 26 ); + methodIndexMap.put( "getMaxChildOverlaps", 27 ); + methodIndexMap.put( "getMaxMixedOverlaps", 28 ); + methodIndexMap.put( "getMaxPairwiseOverlapAdult", 29 ); + methodIndexMap.put( "getMaxPairwiseOverlapChild", 30 ); + methodIndexMap.put( "getWindowBeforeFirstMandJointTour", 31 ); + methodIndexMap.put( "getWindowBetweenFirstLastMandJointTour", 32 ); + methodIndexMap.put( "getWindowAfterLastMandJointTour", 33 ); + methodIndexMap.put( "getNumHhFtWorkers", 34 ); + methodIndexMap.put( "getNumHhPtWorkers", 35 ); + methodIndexMap.put( "getNumHhUnivStudents", 36 ); + methodIndexMap.put( "getNumHhNonWorkAdults", 37 ); + methodIndexMap.put( "getNumHhRetired", 38 ); + methodIndexMap.put( "getNumHhDrivingStudents", 39 ); + methodIndexMap.put( "getNumHhNonDrivingStudents", 40 ); + methodIndexMap.put( "getNumHhPreschool", 41 ); + methodIndexMap.put( "getTravelActiveAdults ", 42 ); + methodIndexMap.put( "getTravelActiveChildren ", 43 ); + methodIndexMap.put( "getNumMandatoryTours", 44 ); + methodIndexMap.put( "getNumJointShoppingTours", 45 ); + methodIndexMap.put( "getNumJointMaintenanceTours", 46 ); + methodIndexMap.put( "getNumJointEatingOutTours", 47 ); + methodIndexMap.put( "getNumJointVisitingTours", 48 ); + methodIndexMap.put( "getNumJointDiscretionaryTours", 49 ); + methodIndexMap.put( "getJTours", 50 ); + methodIndexMap.put( "getPreDrivingAtHome", 51 ); + methodIndexMap.put( "getPreschoolAtHome", 52 ); + } + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getIncomeInDollars(); + case 1: return getHouseholdSize(); + case 2: return getNumAutos(); + case 3: return getCarsEqualsWorkers(); + case 4: return getMoreCarsThanWorkers(); + case 5: return getNumAdults(); + case 6: return getNumChildren(); + case 7: return getPersonIsAdult(); + case 8: return getPersonIsChild(); + case 9: return getPersonIsFullTimeWorker(); + case 10: return getPersonIsPartTimeWorker(); + case 11: return getPersonIsUniversity(); + case 12: return getPersonIsNonworker(); + case 13: return getPersonIsPreschool(); + case 14: return getPersonIsStudentNonDriving(); + case 15: return getPersonIsStudentDriving(); + case 16: return getPersonStaysHome(); + case 17: return getFemale(); + case 18: return getFullTimeWorkers(); + case 19: return getPartTimeWorkers(); + case 20: return getUniversityStudents(); + case 21: return getNonWorkers(); + case 22: return getDrivingAgeStudents(); + case 23: return getNonDrivingAgeStudents(); + case 24: return getPreSchoolers(); + case 25: return getHomeTazIsUrban(); + case 26: return getMaxAdultOverlaps(); + case 27: return getMaxChildOverlaps(); + case 28: return getMaxMixedOverlaps(); + case 29: return getMaxPairwiseOverlapAdult(); + case 30: return getMaxPairwiseOverlapChild(); + case 31: return getWindowBeforeFirstMandJointTour(); + case 32: return getWindowBetweenFirstLastMandJointTour(); + case 33: return getWindowAfterLastMandJointTour(); + case 34: return getNumHhFtWorkers(); + case 35: return getNumHhPtWorkers(); + case 36: return getNumHhUnivStudents(); + case 37: return getNumHhNonWorkAdults(); + case 38: return getNumHhRetired(); + case 39: return getNumHhDrivingStudents(); + case 40: return getNumHhNonDrivingStudents(); + case 41: return getNumHhPreschool(); + case 42: return getTravelActiveAdults (); + case 43: return getTravelActiveChildren (); + case 44: return getNumMandatoryTours(); + case 45: return getNumJointShoppingTours(); + case 46: return getNumJointOthMaintTours(); + case 47: return getNumJointEatOutTours(); + case 48: return getNumJointSocialTours(); + case 49: return getNumJointOthDiscrTours(); + case 50: return getJTours(); + case 51: return getPreDrivingAtHome(); + case 52: return getPreschoolAtHome(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapJointTourFrequencyDMU.java b/src/java/com/pb/cmap/tourBased/CmapJointTourFrequencyDMU.java new file mode 100644 index 0000000..5f9f59f --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapJointTourFrequencyDMU.java @@ -0,0 +1,170 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.JointTourFrequencyDMU; +import com.pb.models.ctrampIf.ModelStructure; + +public class CmapJointTourFrequencyDMU extends JointTourFrequencyDMU { + + + public CmapJointTourFrequencyDMU( ModelStructure modelStructure ){ + super( modelStructure ); + this.modelStructure = modelStructure; + setupMethodIndexMap(); + } + + + /** + * @return 1 if "decision making" household is LOW, 0 otherwise. + */ + public int getHhIncome() { + return hh.getIncomeSegment(); + } + + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getStayHomePatternCountFullTime", 0 ); + methodIndexMap.put( "getStayHomePatternCountPartTime", 1 ); + methodIndexMap.put( "getStayHomePatternCountHomemaker", 2 ); + methodIndexMap.put( "getStayHomePatternCountRetiree", 3 ); + methodIndexMap.put( "getStayHomePatternCountUnivDrivingStudent", 4 ); + methodIndexMap.put( "getStayHomePatternCountNonDrivingChild", 5 ); + methodIndexMap.put( "getNonMandatoryPatternCountFullTime", 6 ); + methodIndexMap.put( "getNonMandatoryPatternCountPartTime", 7 ); + methodIndexMap.put( "getNonMandatoryPatternCountHomemaker", 8 ); + methodIndexMap.put( "getNonMandatoryPatternCountRetiree", 9 ); + methodIndexMap.put( "getNonMandatoryPatternCountUnivDrivingStudent", 10 ); + methodIndexMap.put( "getNonMandatoryPatternCountNonDrivingChild", 11 ); + methodIndexMap.put( "getMandatoryPatternCountFullTime", 12 ); + methodIndexMap.put( "getMandatoryPatternCountDrivingStudent", 13 ); + methodIndexMap.put( "getMandatoryPatternCountNonDrivingChild", 14 ); + methodIndexMap.put( "getTimeWindowOverlapAdult", 15 ); + methodIndexMap.put( "getTimeWindowOverlapChild", 16 ); + methodIndexMap.put( "getTimeWindowOverlapAdultChild", 17 ); + methodIndexMap.put( "getIncomeBetween50And100", 18 ); + methodIndexMap.put( "getIncomeGreaterThan100", 19 ); + methodIndexMap.put( "getAutosInHH", 20 ); + methodIndexMap.put( "getDriverCount", 21 ); + methodIndexMap.put( "getWorkerCount", 22 ); + methodIndexMap.put( "getWalkRetailAccessibility", 23 ); + methodIndexMap.put( "getHhIncome", 24 ); + methodIndexMap.put( "getHouseholdSize", 25 ); + methodIndexMap.put( "getCarsEqualsWorkers", 26 ); + methodIndexMap.put( "getMoreCarsThanWorkers", 27 ); + methodIndexMap.put( "getNumAdults", 28 ); + methodIndexMap.put( "getNumChildren", 29 ); + methodIndexMap.put( "getPersonIsAdult", 30 ); + methodIndexMap.put( "getPersonIsChild", 31 ); + methodIndexMap.put( "getPersonIsFullTimeWorker", 32 ); + methodIndexMap.put( "getPersonIsPartTimeWorker", 33 ); + methodIndexMap.put( "getPersonIsUniversity", 34 ); + methodIndexMap.put( "getPersonIsNonworker", 35 ); + methodIndexMap.put( "getPersonIsPreschool", 36 ); + methodIndexMap.put( "getPersonIsStudentNonDriving", 37 ); + methodIndexMap.put( "getPersonIsStudentDriving", 38 ); + methodIndexMap.put( "getPersonStaysHome", 39 ); + methodIndexMap.put( "getFullTimeWorkers", 40 ); + methodIndexMap.put( "getPartTimeWorkers", 41 ); + methodIndexMap.put( "getUniversityStudents", 42 ); + methodIndexMap.put( "getNonWorkers", 43 ); + methodIndexMap.put( "getDrivingAgeStudents", 44 ); + methodIndexMap.put( "getNonDrivingAgeStudents", 45 ); + methodIndexMap.put( "getPreSchoolers", 46 ); + methodIndexMap.put( "getHomeTazIsUrban", 47 ); + methodIndexMap.put( "getHomeTazIsSuburban", 48 ); + methodIndexMap.put( "getMaxAdultOverlaps", 49 ); + methodIndexMap.put( "getMaxChildOverlaps", 50 ); + methodIndexMap.put( "getMaxMixedOverlaps", 51 ); + methodIndexMap.put( "getMaxPairwiseOverlapAdult", 52 ); + methodIndexMap.put( "getMaxPairwiseOverlapChild", 53 ); + methodIndexMap.put( "getTravelActiveAdults", 54 ); + methodIndexMap.put( "getTravelActiveChildren", 55 ); + methodIndexMap.put( "getTourPurposeIsEat", 56 ); + methodIndexMap.put( "getTourPurposeIsDiscretionary", 57 ); + methodIndexMap.put( "getJointTourComposition", 58 ); + methodIndexMap.put( "getJointTourPurposeIndex", 59 ); + methodIndexMap.put( "getJTours", 60 ); + + } + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getStayHomePatternCountFullTime(); + case 1: return getStayHomePatternCountPartTime(); + case 2: return getStayHomePatternCountHomemaker(); + case 3: return getStayHomePatternCountRetiree(); + case 4: return getStayHomePatternCountUnivDrivingStudent(); + case 5: return getStayHomePatternCountNonDrivingChild(); + case 6: return getNonMandatoryPatternCountFullTime(); + case 7: return getNonMandatoryPatternCountPartTime(); + case 8: return getNonMandatoryPatternCountHomemaker(); + case 9: return getNonMandatoryPatternCountRetiree(); + case 10: return getNonMandatoryPatternCountUnivDrivingStudent(); + case 11: return getNonMandatoryPatternCountNonDrivingChild(); + case 12: return getMandatoryPatternCountFullTime(); + case 13: return getMandatoryPatternCountDrivingStudent(); + case 14: return getMandatoryPatternCountNonDrivingChild(); + case 15: return getTimeWindowOverlapAdult(); + case 16: return getTimeWindowOverlapChild(); + case 17: return getTimeWindowOverlapAdultChild(); + case 18: return getIncomeBetween50And100(); + case 19: return getIncomeGreaterThan100(); + case 20: return getAutosInHH(); + case 21: return getDriverCount(); + case 22: return getWorkerCount(); + case 23: return getWalkRetailAccessibility(); + case 24: return getHhIncome(); + case 25: return getHouseholdSize(); + case 26: return getCarsEqualsWorkers(); + case 27: return getMoreCarsThanWorkers(); + case 28: return getNumAdults(); + case 29: return getNumChildren(); + case 30: return getPersonIsAdult(); + case 31: return getPersonIsChild(); + case 32: return getPersonIsFullTimeWorker(); + case 33: return getPersonIsPartTimeWorker(); + case 34: return getPersonIsUniversity(); + case 35: return getPersonIsNonworker(); + case 36: return getPersonIsPreschool(); + case 37: return getPersonIsStudentNonDriving(); + case 38: return getPersonIsStudentDriving(); + case 39: return getPersonStaysHome(); + case 40: return getFullTimeWorkers(); + case 41: return getPartTimeWorkers(); + case 42: return getUniversityStudents(); + case 43: return getNonWorkers(); + case 44: return getDrivingAgeStudents(); + case 45: return getNonDrivingAgeStudents(); + case 46: return getPreSchoolers(); + case 47: return getHomeTazIsUrban(); + case 48: return getHomeTazIsSuburban(); + case 49: return getMaxAdultOverlaps(); + case 50: return getMaxChildOverlaps(); + case 51: return getMaxMixedOverlaps(); + case 52: return getMaxPairwiseOverlapAdult(); + case 53: return getMaxPairwiseOverlapChild(); + case 54: return getTravelActiveAdults(); + case 55: return getTravelActiveChildren(); + case 56: return getTourPurposeIsEat(); + case 57: return getTourPurposeIsDiscretionary(); + case 58: return getJointTourComposition(); + case 59: return getJointTourPurposeIndex(); + case 60: return getJTours(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapModelStructure.java b/src/java/com/pb/cmap/tourBased/CmapModelStructure.java new file mode 100644 index 0000000..b9c528c --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapModelStructure.java @@ -0,0 +1,1285 @@ +package com.pb.cmap.tourBased; + +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.ModelStructure; + +import java.util.HashMap; +import java.util.ArrayList; + +import org.apache.log4j.Logger; + +public class CmapModelStructure extends ModelStructure { + + + public final String[] MANDATORY_DC_PURPOSE_NAMES = { WORK_PURPOSE_NAME, UNIVERSITY_PURPOSE_NAME, SCHOOL_PURPOSE_NAME }; + public final String[] WORK_PURPOSE_SEGMENT_NAMES = { "OCC1", "OCC2", "OCC3", "OCC4", "OCC5", "OCC6", "OCC7", "OCC8", "OCC9", "OCC10", "OCC11", "OCC12" }; + public final String[] UNIVERSITY_PURPOSE_SEGMENT_NAMES = { }; + public final String[] SCHOOL_PURPOSE_SEGMENT_NAMES = { "PRE", "GRADE", "HIGH" }; + + //DC school segment breaks + public static final int PRESCHOOL_MAX_AGE = 5; + public static final int GRADESCHOOL_MAX_AGE = 13; + + public final int[] CMAP_INCOME_SEGMENT_DOLLAR_LIMITS = {35000, 60000, 100000, Integer.MAX_VALUE}; + + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC1 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC2 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC3 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC4 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC5 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC6 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC7 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC8 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC9 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC10 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC11 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC12 = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_UNIVERSITY = 2; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_PRE = 5; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_GRADE = 4; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_HIGH = 3; + + public final int USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_UNIVERSITY = 2; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_PRE = 5; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_GRADE = 4; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_HIGH = 3; + + public final int USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK = 1; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_UNIVERSITY = 2; + public final int USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_SCHOOL = 3; + + + public final int MANDATORY_STOP_FREQ_UEC_INDEX_WORK = 1; + public final int MANDATORY_STOP_FREQ_UEC_INDEX_UNIVERSITY = 2; + public final int MANDATORY_STOP_FREQ_UEC_INDEX_SCHOOL = 3; + + public final int MANDATORY_STOP_LOC_UEC_INDEX_WORK = 1; + public final int MANDATORY_STOP_LOC_UEC_INDEX_UNIVERSITY = 2; + public final int MANDATORY_STOP_LOC_UEC_INDEX_SCHOOL = 3; + + public final int MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_WORK = 1; + public final int MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_UNIVERSITY = 2; + public final int MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_SCHOOL = 3; + + + + public final String[] NON_MANDATORY_DC_PURPOSE_NAMES = { ESCORT_PURPOSE_NAME, SHOPPING_PURPOSE_NAME, EAT_OUT_PURPOSE_NAME, OTH_MAINT_PURPOSE_NAME, SOCIAL_PURPOSE_NAME, OTH_DISCR_PURPOSE_NAME }; + public final String[] ESCORT_PURPOSE_SEGMENT_NAMES = { }; + + public final String[] SHOPPING_PURPOSE_SEGMENT_NAMES = { }; + public final String[] EAT_OUT_PURPOSE_SEGMENT_NAMES = { }; + public final String[] OTH_MAINT_PURPOSE_SEGMENT_NAMES = { }; + public final String[] SOCIAL_PURPOSE_SEGMENT_NAMES = { }; + public final String[] OTH_DISCR_PURPOSE_SEGMENT_NAMES = { }; + + public final int NON_MANDATORY_SOA_UEC_INDEX_ESCORT = 6; + public final int NON_MANDATORY_SOA_UEC_INDEX_SHOPPING = 7; + public final int NON_MANDATORY_SOA_UEC_INDEX_EAT_OUT = 8; + public final int NON_MANDATORY_SOA_UEC_INDEX_OTHER_MAINT = 9; + public final int NON_MANDATORY_SOA_UEC_INDEX_SOCIAL = 10; + public final int NON_MANDATORY_SOA_UEC_INDEX_OTHER_DISCR = 11; + + public final int NON_MANDATORY_DC_UEC_INDEX_ESCORT = 6; + public final int NON_MANDATORY_DC_UEC_INDEX_SHOPPING = 7; + public final int NON_MANDATORY_DC_UEC_INDEX_EAT_OUT = 8; + public final int NON_MANDATORY_DC_UEC_INDEX_OTHER_MAINT = 9; + public final int NON_MANDATORY_DC_UEC_INDEX_SOCIAL = 10; + public final int NON_MANDATORY_DC_UEC_INDEX_OTHER_DISCR = 11; + + public final int NON_MANDATORY_MC_UEC_INDEX_ESCORT = 4; + public final int NON_MANDATORY_MC_UEC_INDEX_SHOPPING = 5; + public final int NON_MANDATORY_MC_UEC_INDEX_EAT_OUT = 6; + public final int NON_MANDATORY_MC_UEC_INDEX_OTHER_MAINT = 5; + public final int NON_MANDATORY_MC_UEC_INDEX_SOCIAL = 6; + public final int NON_MANDATORY_MC_UEC_INDEX_OTHER_DISCR = 6; + + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_ESCORT = 4; + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_SHOPPING = 5; + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_EAT_OUT = 7; + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_OTHER_MAINT = 6; + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_SOCIAL = 7; + public final int NON_MANDATORY_STOP_FREQ_UEC_INDEX_OTHER_DISCR = 8; + + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_ESCORT = 4; + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_SHOPPING = 5; + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_EAT_OUT = 6; + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_OTHER_MAINT = 7; + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_SOCIAL = 8; + public final int NON_MANDATORY_STOP_LOC_UEC_INDEX_OTHER_DISCR = 9; + + public final int NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX = 4; + + + + public final String[] AT_WORK_DC_PURPOSE_NAMES = { "work-based" }; + public final String[] AT_WORK_DC_SIZE_SEGMENT_NAMES = { }; + + public final int AT_WORK_SOA_UEC_INDEX_EAT = 12; + public final int AT_WORK_SOA_UEC_INDEX_BUSINESS = 12; + public final int AT_WORK_SOA_UEC_INDEX_MAINT = 12; + + public final int AT_WORK_DC_UEC_INDEX_EAT = 12; + public final int AT_WORK_DC_UEC_INDEX_BUSINESS = 12; + public final int AT_WORK_DC_UEC_INDEX_MAINT = 12; + + public final int AT_WORK_MC_UEC_INDEX_EAT = 7; + public final int AT_WORK_MC_UEC_INDEX_BUSINESS = 7; + public final int AT_WORK_MC_UEC_INDEX_MAINT = 7; + + public final int ARC_AT_WORK_PURPOSE_INDEX_EAT = 1; + public final int ARC_AT_WORK_PURPOSE_INDEX_BUSINESS = 2; + public final int ARC_AT_WORK_PURPOSE_INDEX_MAINT = 3; + + public final int AT_WORK_STOP_FREQ_UEC_INDEX_EAT = 9; + public final int AT_WORK_STOP_FREQ_UEC_INDEX_BUSINESS = 9; + public final int AT_WORK_STOP_FREQ_UEC_INDEX_MAINT = 9; + + public final int AT_WORK_STOP_LOC_UEC_INDEX = 10; + + public final int AT_WORK_TRIP_MODE_CHOICE_UEC_INDEX = 5; + + + public static final int[] SOV_ALTS = { 1, 2 }; + public static final int[] HOV_ALTS = { 3, 4, 5, 6 }; + public static final int[] S2_ALTS = { 3, 4 }; + public static final int[] S3_ALTS = { 5, 6 }; + public static final int[] WALK_ALTS = { 7 }; + public static final int[] BIKE_ALTS = { 8 }; + public static final int[] NON_MOTORIZED_ALTS = { 7, 8 }; + public static final int[] TRANSIT_ALTS = { 9, 10, 11, 12 }; + public static final int[] WALK_LOCAL_ALTS = { 9 }; + public static final int[] WALK_PREMIUM_ALTS = { 10 }; + public static final int[] DRIVE_TRANSIT_ALTS = { 11, 12 }; + public static final int[] PNR_ALTS = { 11, 12 }; + public static final int[] KNR_ALTS = { 11, 12 }; + public static final int[] SCHOOL_BUS_ALTS = { 14 }; + public static final int[] TAXI_ALTS = { 13 }; + + public static final int[] TRIP_SOV_ALTS = { 1, 2 }; + public static final int[] TRIP_HOV_ALTS = { 3, 4, 5, 6 }; + + public static final int MAXIMUM_TOUR_MODE_ALT_INDEX = 26; + + + + private static final int DEFAULT_WORK_DEPART_INTERVAL = 6; // 7:00 am + private static final int DEFAULT_WORK_ARRIVE_INTERVAL = 28; // 6:00 pm + private static final int DEFAULT_SCHOOL_DEPART_INTERVAL = 8; // 8:00 am + private static final int DEFAULT_SCHOOL_ARRIVE_INTERVAL = 24; // 4:00 pm + private static final int DEFAULT_UNIVERSITY_DEPART_INTERVAL = 10; // 9:00 am + private static final int DEFAULT_UNIVERSITY_ARRIVE_INTERVAL = 20; // 2:00 pm + private static final int DEFAULT_NON_MANDATORY_DEPART_INTERVAL = 14; // 11:00 am + private static final int DEFAULT_NON_MANDATORY_ARRIVE_INTERVAL = 20; // 2:00 pm + + public static final int P1 = 1; + public static final int P2 = 2; + public static final int P3 = 3; + public static final int P4 = 4; + public static final int P5 = 5; + public static final int P6 = 6; + public static final int P7 = 7; + public static final int P8 = 8; + public static final int[] PERIODS = { -1, P1, P2, P3, P4, P5, P6, P7, P8 }; + + public static final int P1_P1 = 1; + public static final int P1_P2 = 2; + public static final int P1_P3 = 3; + public static final int P1_P4 = 4; + public static final int P1_P5 = 5; + public static final int P1_P6 = 6; + public static final int P1_P7 = 7; + public static final int P1_P8 = 8; + + public static final int P2_P1 = -1; + public static final int P2_P2 = 9; + public static final int P2_P3 = 10; + public static final int P2_P4 = 11; + public static final int P2_P5 = 12; + public static final int P2_P6 = 13; + public static final int P2_P7 = 14; + public static final int P2_P8 = 15; + + public static final int P3_P1 = -1; + public static final int P3_P2 = -1; + public static final int P3_P3 = 16; + public static final int P3_P4 = 17; + public static final int P3_P5 = 18; + public static final int P3_P6 = 19; + public static final int P3_P7 = 20; + public static final int P3_P8 = 21; + + public static final int P4_P1 = -1; + public static final int P4_P2 = -1; + public static final int P4_P3 = -1; + public static final int P4_P4 = 22; + public static final int P4_P5 = 23; + public static final int P4_P6 = 24; + public static final int P4_P7 = 25; + public static final int P4_P8 = 26; + + public static final int P5_P1 = -1; + public static final int P5_P2 = -1; + public static final int P5_P3 = -1; + public static final int P5_P4 = -1; + public static final int P5_P5 = 27; + public static final int P5_P6 = 28; + public static final int P5_P7 = 29; + public static final int P5_P8 = 30; + + public static final int P6_P1 = -1; + public static final int P6_P2 = -1; + public static final int P6_P3 = -1; + public static final int P6_P4 = -1; + public static final int P6_P5 = -1; + public static final int P6_P6 = 31; + public static final int P6_P7 = 32; + public static final int P6_P8 = 33; + + public static final int P7_P1 = -1; + public static final int P7_P2 = -1; + public static final int P7_P3 = -1; + public static final int P7_P4 = -1; + public static final int P7_P5 = -1; + public static final int P7_P6 = -1; + public static final int P7_P7 = 34; + public static final int P7_P8 = 35; + + public static final int P8_P1 = -1; + public static final int P8_P2 = -1; + public static final int P8_P3 = -1; + public static final int P8_P4 = -1; + public static final int P8_P5 = -1; + public static final int P8_P6 = -1; + public static final int P8_P7 = -1; + public static final int P8_P8 = 36; + + public static final int[] PERIOD_COMBINATION_INDICES = { + -1, + P1_P1, P1_P2, P1_P3, P1_P4, P1_P5, P1_P6, P1_P7, P1_P8, + P2_P2, P2_P3, P2_P4, P2_P5, P2_P6, P2_P7, P2_P8, + P3_P3, P3_P4, P3_P5, P3_P6, P3_P7, P3_P8, + P4_P4, P4_P5, P4_P6, P4_P7, P4_P8, + P5_P5, P5_P6, P5_P7, P5_P8, + P6_P6, P6_P7, P6_P8, + P7_P7, P7_P8, + P8_P8 + }; + public static final int[][] PERIOD_COMBINATIONS = { + { }, + { -1, P1_P1, P1_P2, P1_P3, P1_P4, P1_P5, P1_P6, P1_P7, P1_P8 }, + { -1, P2_P1, P2_P2, P2_P3, P2_P4, P2_P5, P2_P6, P2_P7, P2_P8 }, + { -1, P3_P1, P3_P2, P3_P3, P3_P4, P3_P5, P3_P6, P3_P7, P3_P8 }, + { -1, P4_P1, P4_P2, P4_P3, P4_P4, P4_P5, P4_P6, P4_P7, P4_P8 }, + { -1, P5_P1, P5_P2, P5_P3, P5_P4, P5_P5, P5_P6, P5_P7, P5_P8 }, + { -1, P6_P1, P6_P2, P6_P3, P6_P4, P6_P5, P6_P6, P6_P7, P6_P8 }, + { -1, P7_P1, P7_P2, P7_P3, P7_P4, P7_P5, P7_P6, P7_P7, P7_P8 }, + { -1, P8_P1, P8_P2, P8_P3, P8_P4, P8_P5, P8_P6, P8_P7, P8_P8 } + }; + + public static final int UPPER_1 = 3; + public static final int UPPER_2 = 5; + public static final int UPPER_3 = 9; + public static final int UPPER_4 = 11; + public static final int UPPER_5 = 19; + public static final int UPPER_6 = 23; + public static final int UPPER_7 = 27; + public static final int UPPER_8 = 31; + + public static final String[] PERIOD_LABELS = { "", "P1", "P2", "P3", "P4", "P5", "P5", "P7", "P8" }; + + private static final int TIME_INTERVAL_FOR_4_PM = 24; // time interval index associated with 4:00 pm + private static final int TIME_INTERVAL_FOR_7_PM = 30; // time interval index associated with 7:00 pm + + + + public final double[][] CDAP_6_PLUS_PROPORTIONS = { + {0.0, 0.0, 0.0}, {0.79647, 0.09368, 0.10985}, {0.61678, 0.25757, 0.12565}, + {0.69229, 0.15641, 0.15130}, {0.00000, 0.67169, 0.32831}, {0.00000, 0.54295, 0.45705}, + {0.77609, 0.06004, 0.16387}, {0.68514, 0.09144, 0.22342}, {0.14056, 0.06512, 0.79432} }; + + public static final String[] JTF_ALTERNATIVE_LABELS = { + "0_tours", "1_Shop", "1_Main", "1_Eat", "1_Visit", "1_Disc", "2_SS", "2_SM", "2_SE", + "2_SV", "2_SD", "2_MM", "2_ME", "2_MV", "2_MD", "2_EE", "2_EV", "2_ED", "2_VV", "2_VD", + "2_DD" }; + public static final String[] AWF_ALTERNATIVE_LABELS = { + "0_subTours", "1_eat", "1_business", "1_other", "2_business", "2 other", + "2_eat_business" }; + + + + public CmapModelStructure(){ + super(); + + setIncomeSegments( CMAP_INCOME_SEGMENT_DOLLAR_LIMITS ); + + jtfAltLabels = JTF_ALTERNATIVE_LABELS; + awfAltLabels = AWF_ALTERNATIVE_LABELS; + + + dcSizePurposeSegmentMap = new HashMap>(); + + dcSizeIndexSegmentMap = new HashMap(); + dcSizeSegmentIndexMap = new HashMap(); + dcSizeArrayIndexPurposeMap = new HashMap(); + dcSizeArrayPurposeIndexMap = new HashMap(); + + + + setMandatoryPurposeNameValues(); + + setUsualWorkAndSchoolLocationSoaUecSheetIndexValues (); + setUsualWorkAndSchoolLocationUecSheetIndexValues (); + setUsualWorkAndSchoolLocationModeChoiceUecSheetIndexValues (); + + setMandatoryStopFreqUecSheetIndexValues(); + setMandatoryStopLocUecSheetIndexValues(); + setMandatoryTripModeChoiceUecSheetIndexValues(); + + + + + setNonMandatoryPurposeNameValues(); + + setNonMandatoryDcSoaUecSheetIndexValues(); + setNonMandatoryDcUecSheetIndexValues(); + setNonMandatoryModeChoiceUecSheetIndexValues(); + + setNonMandatoryStopFreqUecSheetIndexValues(); + setNonMandatoryStopLocUecSheetIndexValues(); + setNonMandatoryTripModeChoiceUecSheetIndexValues(); + + + + + setAtWorkPurposeNameValues(); + + setAtWorkDcSoaUecSheetIndexValues(); + setAtWorkDcUecSheetIndexValues(); + setAtWorkModeChoiceUecSheetIndexValues(); + + setAtWorkStopFreqUecSheetIndexValues(); + setAtWorkStopLocUecSheetIndexValues(); + setAtWorkTripModeChoiceUecSheetIndexValues(); + + createDcSizePurposeSegmentMap(); + + mapModelSegmentsToDcSizeArraySegments(); + + + } + + private void mapModelSegmentsToDcSizeArraySegments() { + + Logger logger = Logger.getLogger( this.getClass() ); + + dcSizeDcModelPurposeMap = new HashMap(); + dcModelDcSizePurposeMap = new HashMap(); + + // loop over soa model names and map top dc size array indices + for (int i=0; i < dcModelPurposeIndexMap.size(); i++){ + String modelSegment = dcModelIndexPurposeMap.get(i); + + // look for this modelSegment name in the dc size array names map, with and without "_segment". + if ( dcSizeArrayPurposeIndexMap.containsKey(modelSegment) ) { + dcSizeDcModelPurposeMap.put(modelSegment, modelSegment); + dcModelDcSizePurposeMap.put(modelSegment, modelSegment); + } + else { + int underscoreIndex = modelSegment.indexOf('_'); + if ( underscoreIndex < 0 ) { + if ( dcSizeArrayPurposeIndexMap.containsKey( modelSegment + "_" + modelSegment ) ) { + dcSizeDcModelPurposeMap.put( modelSegment + "_" + modelSegment, modelSegment ); + dcModelDcSizePurposeMap.put( modelSegment, modelSegment + "_" + modelSegment ); + } + else { + logger.error( String.format("could not establish correspondence between DC SOA model purpose string = %s", modelSegment) ); + logger.error( String.format("and a DC array purpose string:") ); + int j=0; + for ( String key : dcSizeArrayPurposeIndexMap.keySet() ) + logger.error( String.format("%-2d: %s", ++j, key) ); + throw new RuntimeException(); + } + } + else { + // all at-work size segments should map to one model segment + if ( modelSegment.substring(0,underscoreIndex).equalsIgnoreCase(AT_WORK_PURPOSE_NAME) ) { + dcSizeDcModelPurposeMap.put( AT_WORK_PURPOSE_NAME + "_" + AT_WORK_PURPOSE_NAME, modelSegment ); + dcModelDcSizePurposeMap.put( modelSegment, AT_WORK_PURPOSE_NAME + "_" + AT_WORK_PURPOSE_NAME ); + } + else { + logger.error( String.format("could not establish correspondence between DC SOA model purpose string = %s", modelSegment) ); + logger.error( String.format("and a DC array purpose string:") ); + int j=0; + for ( String key : dcSizeArrayPurposeIndexMap.keySet() ) + logger.error( String.format("%-2d: %s", ++j, key) ); + throw new RuntimeException(); + } + } + } + + } + + } + + public void setIncomeSegments( int[] incomeBreakPoints ) { + incomeSegmentDollarLimits = new int[incomeBreakPoints.length]; + for(int i=0; i < incomeBreakPoints.length; i++) + incomeSegmentDollarLimits[i] = incomeBreakPoints[i]; + } + + public int getIncomeSegment( int hhIncomeInDollars ) { + for (int i=0; i< incomeSegmentDollarLimits.length; i++) { + if ( hhIncomeInDollars < incomeSegmentDollarLimits[i] ) { + return i+1; + } + } + throw new RuntimeException("Invalid income segments defined in ModelStructure"); + } + + public String getSchoolPurpose( int age ) { + + if ( age <= PRESCHOOL_MAX_AGE ) + return (schoolPurposeName + "_" + SCHOOL_PURPOSE_SEGMENT_NAMES[0]).toLowerCase(); + else if ( age <= GRADESCHOOL_MAX_AGE ) + return (schoolPurposeName + "_" + SCHOOL_PURPOSE_SEGMENT_NAMES[1]).toLowerCase(); + else + return (schoolPurposeName + "_" + SCHOOL_PURPOSE_SEGMENT_NAMES[2]).toLowerCase(); + } + + public String getSchoolPurpose() { + return schoolPurposeName.toLowerCase(); + } + + public String getUniversityPurpose() { + return universityPurposeName.toLowerCase(); + } + + public String getWorkPurposeFromIncomeInDollars( int hhIncomeInDollars ) { + return getWorkPurposeFromIncomeInDollars( false, hhIncomeInDollars ); + } + + public String getWorkPurposeFromIncomeInDollars( boolean isPtWorker, int hhIncomeInDollars ) { + if ( isPtWorker ) { + return (workPurposeName + "_" + WORK_PURPOSE_SEGMENT_NAMES[WORK_PURPOSE_SEGMENT_NAMES.length-1]).toLowerCase(); + } else { + int incomeSegment = getIncomeSegment(hhIncomeInDollars); + return (workPurposeName + "_" + WORK_PURPOSE_SEGMENT_NAMES[incomeSegment-1]).toLowerCase(); + } + } + + + public boolean getTourModeIsBike( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < BIKE_ALTS.length; i++ ) { + if ( BIKE_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsWalk( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < WALK_ALTS.length; i++ ) { + if ( WALK_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsWalkLocal( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < WALK_LOCAL_ALTS.length; i++ ) { + if ( WALK_LOCAL_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsWalkPremium( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < WALK_PREMIUM_ALTS.length; i++ ) { + if ( WALK_PREMIUM_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + + public boolean getTourModeIsTransit( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < TRANSIT_ALTS.length; i++ ) { + if ( TRANSIT_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsDriveTransit( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < DRIVE_TRANSIT_ALTS.length; i++ ) { + if ( DRIVE_TRANSIT_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsPnr(int tourMode) + { + boolean returnValue = false; + for (int i = 0; i < PNR_ALTS.length; i++) + { + if (PNR_ALTS[i] == tourMode) + { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsKnr(int tourMode) + { + boolean returnValue = false; + for (int i = 0; i < KNR_ALTS.length; i++) + { + if (KNR_ALTS[i] == tourMode) + { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsSchoolBus( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < SCHOOL_BUS_ALTS.length; i++ ) { + if ( SCHOOL_BUS_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsTaxi( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < TAXI_ALTS.length; i++ ) { + if ( TAXI_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsHov(int tourMode) { + boolean returnValue = false; + for ( int i=0; i < HOV_ALTS.length; i++ ) { + if ( HOV_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsS2(int tourMode) { + boolean returnValue = false; + for ( int i=0; i < S2_ALTS.length; i++ ) { + if ( S2_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsS3(int tourMode) { + boolean returnValue = false; + for ( int i=0; i < S3_ALTS.length; i++ ) { + if ( S3_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTripModeIsSovOrHov( int tripMode ) { + + for ( int i=0; i < TRIP_SOV_ALTS.length; i++ ) { + if ( TRIP_SOV_ALTS[i] == tripMode ) + return true; + } + + for ( int i=0; i < TRIP_HOV_ALTS.length; i++ ) { + if ( TRIP_HOV_ALTS[i] == tripMode ) + return true; + } + + return false; + } + + + public boolean getTourModeIsSov( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < SOV_ALTS.length; i++ ) { + if ( SOV_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + public boolean getTourModeIsSovOrHov( int tourMode ) { + for ( int i=0; i < SOV_ALTS.length; i++ ) { + if ( SOV_ALTS[i] == tourMode ) + return true; + } + + for ( int i=0; i < HOV_ALTS.length; i++ ) { + if ( HOV_ALTS[i] == tourMode ) + return true; + } + + return false; + } + + public boolean getTourModeIsNonMotorized( int tourMode ) { + boolean returnValue = false; + for ( int i=0; i < NON_MOTORIZED_ALTS.length; i++ ) { + if ( NON_MOTORIZED_ALTS[i] == tourMode ) { + returnValue = true; + break; + } + } + return returnValue; + } + + + + + private int createPurposeIndexMaps( String purposeName, String[] segmentNames, int index, String categoryString ) { + + HashMap segmentMap = new HashMap(); + String key = ""; + if ( segmentNames.length > 0 ) { + for ( int i=0; i < segmentNames.length; i++ ) { + segmentMap.put ( segmentNames[i].toLowerCase(), i ); + key = purposeName.toLowerCase() + "_" + segmentNames[i].toLowerCase(); + dcSizeIndexSegmentMap.put ( index, key ); + dcSizeSegmentIndexMap.put ( key, index++ ); + } + } + else { + segmentMap.put ( purposeName.toLowerCase(), 0 ); + key = purposeName.toLowerCase() + "_" + purposeName.toLowerCase(); + dcSizeIndexSegmentMap.put ( index, key ); + dcSizeSegmentIndexMap.put ( key, index++ ); + } + dcSizePurposeSegmentMap.put( purposeName.toLowerCase(), segmentMap ); + + return index; + + } + + + /** + * This method defines the segmentation for which destination choice size variables are calculated. + */ + private void createDcSizePurposeSegmentMap() { + + int index = 0; + + // put work purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( WORK_PURPOSE_NAME, WORK_PURPOSE_SEGMENT_NAMES, index, MANDATORY_CATEGORY ); + + // put university purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( UNIVERSITY_PURPOSE_NAME, UNIVERSITY_PURPOSE_SEGMENT_NAMES, index, MANDATORY_CATEGORY ); + + // put school purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( SCHOOL_PURPOSE_NAME, SCHOOL_PURPOSE_SEGMENT_NAMES, index, MANDATORY_CATEGORY ); + + // put escort purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( ESCORT_PURPOSE_NAME, ESCORT_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put shopping purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( SHOPPING_PURPOSE_NAME, SHOPPING_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put eat out purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( EAT_OUT_PURPOSE_NAME, EAT_OUT_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put oth main purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( OTH_MAINT_PURPOSE_NAME, OTH_MAINT_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put social purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( SOCIAL_PURPOSE_NAME, SOCIAL_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put oth discr purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( OTH_DISCR_PURPOSE_NAME, OTH_DISCR_PURPOSE_SEGMENT_NAMES, index, INDIVIDUAL_NON_MANDATORY_CATEGORY ); + + // put at work purpose segments, by which DC Size calculations are segmented, into a map to be stored by purpose name. + index = createPurposeIndexMaps( AT_WORK_PURPOSE_NAME, AT_WORK_DC_SIZE_SEGMENT_NAMES, index, AT_WORK_CATEGORY ); + + } + + public HashMap> getDcSizePurposeSegmentMap() { + return dcSizePurposeSegmentMap; + } + + + + + private void setMandatoryPurposeNameValues() { + + int index = 0; + + int numDcSizePurposeSegments = 0; + if ( WORK_PURPOSE_SEGMENT_NAMES.length > 0 ) + numDcSizePurposeSegments += WORK_PURPOSE_SEGMENT_NAMES.length; + else + numDcSizePurposeSegments += 1; + if ( UNIVERSITY_PURPOSE_SEGMENT_NAMES.length > 0 ) + numDcSizePurposeSegments += UNIVERSITY_PURPOSE_SEGMENT_NAMES.length; + else + numDcSizePurposeSegments += 1; + if ( SCHOOL_PURPOSE_SEGMENT_NAMES.length > 0 ) + numDcSizePurposeSegments += SCHOOL_PURPOSE_SEGMENT_NAMES.length; + else + numDcSizePurposeSegments += 1; + + + mandatoryDcModelPurposeNames = new String[numDcSizePurposeSegments]; + + + + workPurposeName = WORK_PURPOSE_NAME.toLowerCase(); + workPurposeSegmentNames = new String[WORK_PURPOSE_SEGMENT_NAMES.length]; + if ( workPurposeSegmentNames.length > 0 ) { + for ( int i=0; i < WORK_PURPOSE_SEGMENT_NAMES.length; i++ ) { + workPurposeSegmentNames[i] = WORK_PURPOSE_SEGMENT_NAMES[i].toLowerCase(); + mandatoryDcModelPurposeNames[index] = workPurposeName + "_" + workPurposeSegmentNames[i]; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each work purpose_segment + dcSizeArrayIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + dcSizeArrayPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + index++; + } + } + else { + mandatoryDcModelPurposeNames[index] = workPurposeName; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each work purpose_segment + String name = mandatoryDcModelPurposeNames[index] + "_" + mandatoryDcModelPurposeNames[index]; + dcSizeArrayIndexPurposeMap.put( index, name ); + dcSizeArrayPurposeIndexMap.put( name, index ); + index++; + } + + universityPurposeName = UNIVERSITY_PURPOSE_NAME.toLowerCase(); + universityPurposeSegmentNames = new String[UNIVERSITY_PURPOSE_SEGMENT_NAMES.length]; + if ( universityPurposeSegmentNames.length > 0 ) { + for ( int i=0; i < universityPurposeSegmentNames.length; i++ ) { + universityPurposeSegmentNames[i] = UNIVERSITY_PURPOSE_SEGMENT_NAMES[i].toLowerCase(); + mandatoryDcModelPurposeNames[index] = universityPurposeName + "_" + universityPurposeSegmentNames[i]; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each university purpose_segment + dcSizeArrayIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + dcSizeArrayPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + index++; + } + } + else { + mandatoryDcModelPurposeNames[index] = universityPurposeName; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each university purpose_segment + String name = mandatoryDcModelPurposeNames[index] + "_" + mandatoryDcModelPurposeNames[index]; + dcSizeArrayIndexPurposeMap.put( index, name ); + dcSizeArrayPurposeIndexMap.put( name, index ); + index++; + } + + schoolPurposeName = SCHOOL_PURPOSE_NAME.toLowerCase(); + schoolPurposeSegmentNames = new String[SCHOOL_PURPOSE_SEGMENT_NAMES.length]; + if ( schoolPurposeSegmentNames.length > 0 ) { + for ( int i=0; i < schoolPurposeSegmentNames.length; i++ ) { + schoolPurposeSegmentNames[i] = SCHOOL_PURPOSE_SEGMENT_NAMES[i].toLowerCase(); + mandatoryDcModelPurposeNames[index] = schoolPurposeName + "_" + schoolPurposeSegmentNames[i]; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each school purpose_segment + dcSizeArrayIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + dcSizeArrayPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + index++; + } + } + else { + mandatoryDcModelPurposeNames[index] = schoolPurposeName; + dcModelPurposeIndexMap.put( mandatoryDcModelPurposeNames[index], index ); + dcModelIndexPurposeMap.put( index, mandatoryDcModelPurposeNames[index] ); + + // a separate size term is calculated for each school purpose_segment + String name = mandatoryDcModelPurposeNames[index] + "_" + mandatoryDcModelPurposeNames[index]; + dcSizeArrayIndexPurposeMap.put( index, name ); + dcSizeArrayPurposeIndexMap.put( name, index ); + } + + + } + + + private void setUsualWorkAndSchoolLocationSoaUecSheetIndexValues () { + dcSoaUecIndexMap.put( "work_occ1", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC1 ); + dcSoaUecIndexMap.put( "work_occ2", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC2 ); + dcSoaUecIndexMap.put( "work_occ3", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC3 ); + dcSoaUecIndexMap.put( "work_occ4", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC4 ); + dcSoaUecIndexMap.put( "work_occ5", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC5 ); + dcSoaUecIndexMap.put( "work_occ6", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC6 ); + dcSoaUecIndexMap.put( "work_occ7", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC7 ); + dcSoaUecIndexMap.put( "work_occ8", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC8 ); + dcSoaUecIndexMap.put( "work_occ9", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC9 ); + dcSoaUecIndexMap.put( "work_occ10", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC10 ); + dcSoaUecIndexMap.put( "work_occ11", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC11 ); + dcSoaUecIndexMap.put( "work_occ12", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_OCC12 ); + + dcSoaUecIndexMap.put( "university", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_UNIVERSITY ); + dcSoaUecIndexMap.put( "school_pre", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_PRE ); + dcSoaUecIndexMap.put( "school_grade", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_GRADE ); + dcSoaUecIndexMap.put( "school_high", USUAL_WORK_AND_SCHOOL_LOCATION_SOA_UEC_INDEX_SCHOOL_HIGH ); + } + + + private void setUsualWorkAndSchoolLocationUecSheetIndexValues () { + dcUecIndexMap.put( "work_occ1", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ2", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ3", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ4", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ5", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ6", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ7", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ8", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ9", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ10", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ11", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "work_occ12", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_WORK ); + dcUecIndexMap.put( "university", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_UNIVERSITY ); + dcUecIndexMap.put( "school_pre", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_PRE ); + dcUecIndexMap.put( "school_grade", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_GRADE ); + dcUecIndexMap.put( "school_high", USUAL_WORK_AND_SCHOOL_LOCATION_UEC_INDEX_SCHOOL_HIGH ); + } + + + private void setUsualWorkAndSchoolLocationModeChoiceUecSheetIndexValues () { + tourModeChoiceUecIndexMap.put( "work_occ1", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ2", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ3", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ4", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ5", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ6", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ7", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ8", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ9", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ10", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ11", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + tourModeChoiceUecIndexMap.put( "work_occ12", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_WORK ); + + tourModeChoiceUecIndexMap.put( "university", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_UNIVERSITY ); + tourModeChoiceUecIndexMap.put( "school_pre", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_SCHOOL ); + tourModeChoiceUecIndexMap.put( "school_grade", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_SCHOOL ); + tourModeChoiceUecIndexMap.put( "school_high", USUAL_WORK_AND_SCHOOL_LOCATION_MODE_CHOICE_UEC_INDEX_SCHOOL ); + + } + + + private void setMandatoryStopFreqUecSheetIndexValues () { + + stopFreqUecIndexMap.put( "work_occ1", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ2", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ3", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ4", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ5", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ6", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ7", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ8", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ9", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ10", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ11", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + stopFreqUecIndexMap.put( "work_occ12", MANDATORY_STOP_FREQ_UEC_INDEX_WORK ); + + stopFreqUecIndexMap.put( "university", MANDATORY_STOP_FREQ_UEC_INDEX_UNIVERSITY ); + stopFreqUecIndexMap.put( "school_pre", MANDATORY_STOP_FREQ_UEC_INDEX_SCHOOL ); + stopFreqUecIndexMap.put( "school_grade", MANDATORY_STOP_FREQ_UEC_INDEX_SCHOOL ); + stopFreqUecIndexMap.put( "school_high", MANDATORY_STOP_FREQ_UEC_INDEX_SCHOOL ); + } + + private void setMandatoryStopLocUecSheetIndexValues () { + stopLocUecIndexMap.put( WORK_PURPOSE_NAME, MANDATORY_STOP_LOC_UEC_INDEX_WORK ); + stopLocUecIndexMap.put( UNIVERSITY_PURPOSE_NAME, MANDATORY_STOP_LOC_UEC_INDEX_UNIVERSITY ); + stopLocUecIndexMap.put( SCHOOL_PURPOSE_NAME, MANDATORY_STOP_LOC_UEC_INDEX_SCHOOL ); + } + + private void setMandatoryTripModeChoiceUecSheetIndexValues () { + tripModeChoiceUecIndexMap.put( WORK_PURPOSE_NAME, MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_WORK ); + tripModeChoiceUecIndexMap.put( UNIVERSITY_PURPOSE_NAME, MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_UNIVERSITY ); + tripModeChoiceUecIndexMap.put( SCHOOL_PURPOSE_NAME, MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX_SCHOOL ); + } + + + + private void setNonMandatoryPurposeNameValues() { + + // initialize index to the length of the mandatory names list already developed. + int index = dcSizeArrayPurposeIndexMap.size(); + + + ESCORT_SEGMENT_NAMES = ESCORT_PURPOSE_SEGMENT_NAMES; + + // ESCORT is the only non-mandatory purpose with segments + ArrayList purposeNamesList = new ArrayList(); + for ( int i=0; i < NON_MANDATORY_DC_PURPOSE_NAMES.length; i++ ) { + if ( NON_MANDATORY_DC_PURPOSE_NAMES[i].equalsIgnoreCase( ESCORT_PURPOSE_NAME ) & getNumEscortSegments() > 0 ) { + for ( int j=0; j < ESCORT_SEGMENT_NAMES.length; j++ ) { + String name = (ESCORT_PURPOSE_NAME + "_" + ESCORT_SEGMENT_NAMES[j]).toLowerCase(); + purposeNamesList.add( name ); + dcModelPurposeIndexMap.put( name, index ); + dcModelIndexPurposeMap.put( index, name ); + + // a separate size term is calculated for each non-mandatory purpose_segment + dcSizeArrayIndexPurposeMap.put( index, name ); + dcSizeArrayPurposeIndexMap.put( name, index ); + index++; + } + } + else { + String name = NON_MANDATORY_DC_PURPOSE_NAMES[i].toLowerCase(); + purposeNamesList.add( name ); + dcModelPurposeIndexMap.put( name, index ); + dcModelIndexPurposeMap.put( index, name ); + + // a separate size term is calculated for each non-mandatory purpose_segment + dcSizeArrayIndexPurposeMap.put( index, name+"_"+name ); + dcSizeArrayPurposeIndexMap.put( name+"_"+name, index ); + index++; + } + } + + int escortOffset = ESCORT_SEGMENT_NAMES.length; + + jointDcModelPurposeNames = new String[purposeNamesList.size()-escortOffset]; + nonMandatoryDcModelPurposeNames = new String[purposeNamesList.size()]; + for ( int i=0; i < purposeNamesList.size(); i++ ) { + nonMandatoryDcModelPurposeNames[i] = purposeNamesList.get(i); + if ( i > escortOffset - 1 ) + jointDcModelPurposeNames[i-escortOffset] = purposeNamesList.get(i); + } + + } + + + private void setNonMandatoryDcSoaUecSheetIndexValues () { + dcSoaUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_ESCORT ); + dcSoaUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_SHOPPING ); + dcSoaUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_EAT_OUT ); + dcSoaUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_OTHER_MAINT ); + dcSoaUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_SOCIAL ); + dcSoaUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_SOA_UEC_INDEX_OTHER_DISCR ); + } + + + private void setNonMandatoryDcUecSheetIndexValues () { + dcUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_ESCORT ); + dcUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_SHOPPING ); + dcUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_EAT_OUT ); + dcUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_OTHER_MAINT ); + dcUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_SOCIAL ); + dcUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_DC_UEC_INDEX_OTHER_DISCR ); + } + + + private void setNonMandatoryModeChoiceUecSheetIndexValues () { + tourModeChoiceUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_ESCORT ); + tourModeChoiceUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_SHOPPING ); + tourModeChoiceUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_EAT_OUT ); + tourModeChoiceUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_OTHER_MAINT ); + tourModeChoiceUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_SOCIAL ); + tourModeChoiceUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_MC_UEC_INDEX_OTHER_DISCR ); + } + + private void setNonMandatoryStopFreqUecSheetIndexValues () { + stopFreqUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_ESCORT ); + stopFreqUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_SHOPPING ); + stopFreqUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_EAT_OUT ); + stopFreqUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_OTHER_MAINT ); + stopFreqUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_SOCIAL ); + stopFreqUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_STOP_FREQ_UEC_INDEX_OTHER_DISCR ); + } + + private void setNonMandatoryStopLocUecSheetIndexValues () { + stopLocUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_ESCORT ); + stopLocUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_SHOPPING ); + stopLocUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_EAT_OUT ); + stopLocUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_OTHER_MAINT ); + stopLocUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_SOCIAL ); + stopLocUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_STOP_LOC_UEC_INDEX_OTHER_DISCR ); + } + + private void setNonMandatoryTripModeChoiceUecSheetIndexValues () { + tripModeChoiceUecIndexMap.put( ESCORT_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + tripModeChoiceUecIndexMap.put( SHOPPING_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + tripModeChoiceUecIndexMap.put( EAT_OUT_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + tripModeChoiceUecIndexMap.put( OTH_MAINT_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + tripModeChoiceUecIndexMap.put( SOCIAL_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + tripModeChoiceUecIndexMap.put( OTH_DISCR_PURPOSE_NAME, NON_MANDATORY_TRIP_MODE_CHOICE_UEC_INDEX ); + } + + + private void setAtWorkPurposeNameValues() { + + AT_WORK_PURPOSE_INDEX_EAT = ARC_AT_WORK_PURPOSE_INDEX_EAT; + AT_WORK_PURPOSE_INDEX_BUSINESS = ARC_AT_WORK_PURPOSE_INDEX_BUSINESS; + AT_WORK_PURPOSE_INDEX_MAINT = ARC_AT_WORK_PURPOSE_INDEX_MAINT; + + AT_WORK_SEGMENT_NAMES = new String[3]; + AT_WORK_SEGMENT_NAMES[0] = AT_WORK_EAT_PURPOSE_NAME; + AT_WORK_SEGMENT_NAMES[1] = AT_WORK_BUSINESS_PURPOSE_NAME; + AT_WORK_SEGMENT_NAMES[2] = AT_WORK_MAINT_PURPOSE_NAME; + + + // initialize index to the length of the home-based tour names list already developed. + int index = dcSizeArrayPurposeIndexMap.size(); + + // the same size term is used by each at-work soa model + dcSizeArrayIndexPurposeMap.put( index, AT_WORK_PURPOSE_NAME+"_"+AT_WORK_PURPOSE_NAME ); + dcSizeArrayPurposeIndexMap.put( AT_WORK_PURPOSE_NAME+"_"+AT_WORK_PURPOSE_NAME, index ); + + ArrayList purposeNamesList = new ArrayList(); + for ( int j=0; j < AT_WORK_SEGMENT_NAMES.length; j++ ) { + String name = ( AT_WORK_PURPOSE_NAME + "_" + AT_WORK_SEGMENT_NAMES[j]).toLowerCase(); + purposeNamesList.add( name ); + dcModelPurposeIndexMap.put( name, index ); + dcModelIndexPurposeMap.put( index, name ); + index++; + } + + + atWorkDcModelPurposeNames = new String[purposeNamesList.size()]; + for ( int i=0; i < purposeNamesList.size(); i++ ) { + atWorkDcModelPurposeNames[i] = purposeNamesList.get(i); + } + + } + + + private void setAtWorkDcSoaUecSheetIndexValues () { + dcSoaUecIndexMap.put( "work-based_eat", AT_WORK_SOA_UEC_INDEX_EAT ); + dcSoaUecIndexMap.put( "work-based_business", AT_WORK_SOA_UEC_INDEX_BUSINESS ); + dcSoaUecIndexMap.put( "work-based_maint", AT_WORK_SOA_UEC_INDEX_MAINT ); + } + + + private void setAtWorkDcUecSheetIndexValues () { + dcUecIndexMap.put( "work-based_eat", AT_WORK_DC_UEC_INDEX_EAT ); + dcUecIndexMap.put( "work-based_business", AT_WORK_DC_UEC_INDEX_BUSINESS ); + dcUecIndexMap.put( "work-based_maint", AT_WORK_DC_UEC_INDEX_MAINT ); + } + + + private void setAtWorkModeChoiceUecSheetIndexValues () { + tourModeChoiceUecIndexMap.put( "work-based_eat", AT_WORK_MC_UEC_INDEX_EAT ); + tourModeChoiceUecIndexMap.put( "work-based_business", AT_WORK_MC_UEC_INDEX_BUSINESS ); + tourModeChoiceUecIndexMap.put( "work-based_maint", AT_WORK_MC_UEC_INDEX_MAINT ); + } + + + private void setAtWorkStopFreqUecSheetIndexValues () { + stopFreqUecIndexMap.put( "work-based_eat", AT_WORK_STOP_FREQ_UEC_INDEX_EAT ); + stopFreqUecIndexMap.put( "work-based_business", AT_WORK_STOP_FREQ_UEC_INDEX_BUSINESS ); + stopFreqUecIndexMap.put( "work-based_maint", AT_WORK_STOP_FREQ_UEC_INDEX_MAINT ); + } + + private void setAtWorkStopLocUecSheetIndexValues () { + stopLocUecIndexMap.put( AT_WORK_PURPOSE_NAME, AT_WORK_STOP_LOC_UEC_INDEX ); + } + + private void setAtWorkTripModeChoiceUecSheetIndexValues () { + tripModeChoiceUecIndexMap.put( AT_WORK_PURPOSE_NAME, AT_WORK_TRIP_MODE_CHOICE_UEC_INDEX ); + } + + + + + public double[][] getCdap6PlusProps() { + return CDAP_6_PLUS_PROPORTIONS; + } + + + + public int getWorkLocationDefaultDepartPeriod() { + return DEFAULT_WORK_DEPART_INTERVAL; + } + + public int getWorkLocationDefaultArrivePeriod() { + return DEFAULT_WORK_ARRIVE_INTERVAL; + } + + public int getSchoolLocationDefaultDepartPeriod() { + return DEFAULT_SCHOOL_DEPART_INTERVAL; + } + + public int getSchoolLocationDefaultArrivePeriod() { + return DEFAULT_SCHOOL_ARRIVE_INTERVAL; + } + + public int getUniversityLocationDefaultDepartPeriod() { + return DEFAULT_UNIVERSITY_DEPART_INTERVAL; + } + + public int getUniversityLocationDefaultArrivePeriod() { + return DEFAULT_UNIVERSITY_ARRIVE_INTERVAL; + } + + public int getNonMandatoryLocationDefaultDepartPeriod() { + return DEFAULT_NON_MANDATORY_DEPART_INTERVAL; + } + + public int getNonMandatoryLocationDefaultArrivePeriod() { + return DEFAULT_NON_MANDATORY_ARRIVE_INTERVAL; + } + + + public int[] getPeriodCombinationIndices() + { + return PERIOD_COMBINATION_INDICES; + } + + public int getPeriodCombinationIndex(int departInterval, int arriveInterval) + { + + int departPeriodIndex = getPeriodIndex(departInterval); + int arrivePeriodIndex = getPeriodIndex(arriveInterval); + + if ( PERIOD_COMBINATIONS[departPeriodIndex][arrivePeriodIndex] < 0 ) { + String errorString = String.format( "departInterval=%d, arriveInterval=%d, departPeriodIndex=%d, arrivePeriodIndex=%d is invalid period combination.", departInterval, arriveInterval, departPeriodIndex, arrivePeriodIndex ); + throw new RuntimeException(errorString); + } + else { + return PERIOD_COMBINATIONS[departPeriodIndex][arrivePeriodIndex]; + } + + } + + /** + * return the period index + */ + public int getPeriodIndex(int departPeriod) + { + + int periodIndex = 0; + + if (departPeriod <= UPPER_1) + periodIndex = P1; + else if (departPeriod <= UPPER_2) + periodIndex = P2; + else if (departPeriod <= UPPER_3) + periodIndex = P3; + else if (departPeriod <= UPPER_4) + periodIndex = P4; + else if (departPeriod <= UPPER_5) + periodIndex = P5; + else if (departPeriod <= UPPER_6) + periodIndex = P6; + else if (departPeriod <= UPPER_7) + periodIndex = P7; + else + periodIndex = P8; + + return periodIndex; + + } + + /** + * return the tod skim period + */ + public int getTod(int period) { + + int modelPeriod = 0; + + if ( period >= 1 && period < 4 ) + modelPeriod = 1; + else if ( period < 6 ) + modelPeriod = 2; + else if ( period < 10 ) + modelPeriod = 3; + else if ( period < 12 ) + modelPeriod = 4; + else if ( period < 20 ) + modelPeriod = 5; + else if ( period < 24 ) + modelPeriod = 6; + else if ( period < 28 ) + modelPeriod = 7; + else if ( period < 32 ) + modelPeriod = 8; + else + modelPeriod = 1; + + return(modelPeriod); + } + + + public int getIntervalFor4Pm() { + return TIME_INTERVAL_FOR_4_PM; + } + + public int getIntervalFor7Pm() { + return TIME_INTERVAL_FOR_7_PM; + } + + public String getPeriodLabel(int period) + { + return PERIOD_LABELS[period]; + } + + + + + public int getMaxTourModeIndex() { + return MAXIMUM_TOUR_MODE_ALT_INDEX; + } + + public void setJtfAltLabels( String[] labels ) + { + jtfAltLabels = labels; + } + + public String[] getJtfAltLabels() + { + return jtfAltLabels; + } + +} + \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapParkingChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapParkingChoiceDMU.java new file mode 100644 index 0000000..a538c61 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapParkingChoiceDMU.java @@ -0,0 +1,81 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.ParkingChoiceDMU; +import com.pb.models.ctrampIf.TazDataIf; + + + +public class CmapParkingChoiceDMU extends ParkingChoiceDMU { + + + TazDataIf tazDataManager; + + public CmapParkingChoiceDMU( TazDataIf tazDataManager, ModelStructure modelStructure ){ + super( tazDataManager ); + setupMethodIndexMap( modelStructure ); + + this.tazDataManager = tazDataManager; + } + + public double getOMazDMazDistanceAlt ( int alt ) { + int destZone = parkTazs[alt-1]; + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), destZone); + } + + public double getAltDMazDistanceAlt ( int alt ) { + int altZone = parkTazs[alt-1]; + return tazDataManager.getOMazDMazDistance(altZone, dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap( ModelStructure modelStructure ) { + + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getParkTazCbdAreaTypeAlt", 0 ); + methodIndexMap.put( "getTourIsJoint", 1 ); + methodIndexMap.put( "getParkingCostAlt", 2 ); + methodIndexMap.put( "getParkTot", 3 ); + methodIndexMap.put( "getParkTotAlt", 4 ); + + methodIndexMap.put( "getOMazDMazDistanceAlt", 20 ); + methodIndexMap.put( "getAltDMazDistanceAlt", 21 ); + + // populate map of hours parked per day by purpose name + averageDailyHoursParkedMap = new HashMap(); + averageDailyHoursParkedMap.put( modelStructure.WORK_PURPOSE_NAME, 7.9f ); + averageDailyHoursParkedMap.put( modelStructure.UNIVERSITY_PURPOSE_NAME, 6.2f ); + averageDailyHoursParkedMap.put( modelStructure.SCHOOL_PURPOSE_NAME, 7.9f ); + averageDailyHoursParkedMap.put( modelStructure.ESCORT_PURPOSE_NAME, 1.1f ); + averageDailyHoursParkedMap.put( modelStructure.SHOPPING_PURPOSE_NAME, 1.7f ); + averageDailyHoursParkedMap.put( modelStructure.OTH_MAINT_PURPOSE_NAME, 2.8f ); + averageDailyHoursParkedMap.put( modelStructure.EAT_OUT_PURPOSE_NAME, 2.2f ); + averageDailyHoursParkedMap.put( modelStructure.SOCIAL_PURPOSE_NAME, 3.0f ); + averageDailyHoursParkedMap.put( modelStructure.OTH_DISCR_PURPOSE_NAME, 2.7f ); + averageDailyHoursParkedMap.put( modelStructure.AT_WORK_PURPOSE_NAME, 0.6f ); + + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getParkTazCbdAreaTypeAlt( arrayIndex ); + case 1: return getTourIsJoint(); + case 2: return getParkingCostAlt( arrayIndex ); + case 3: return getParkTot(); + case 4: return getParkTotAlt( arrayIndex ); + + case 20: return getOMazDMazDistanceAlt( arrayIndex ); + case 21: return getAltDMazDistanceAlt( arrayIndex ); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapStopDCSoaDMU.java b/src/java/com/pb/cmap/tourBased/CmapStopDCSoaDMU.java new file mode 100644 index 0000000..2c5fca9 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapStopDCSoaDMU.java @@ -0,0 +1,102 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.cmap.tourBased.CmapModelStructure; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.StopDCSoaDMU; + + +public class CmapStopDCSoaDMU extends StopDCSoaDMU { + + CmapModelStructure modelStructure; + + TazDataIf tazDataManager; + + public CmapStopDCSoaDMU( TazDataIf tazDataManager, CmapModelStructure modelStructure ) { + super ( tazDataManager, modelStructure ); + this.modelStructure = modelStructure; + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + } + + public double getOMazDMazDistanceAlt ( int alt ) { + int destZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), destZone); + } + + public double getAltDMazDistanceAlt ( int alt ) { + int altZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(altZone, dmuIndex.getDestZone()); + } + + public int getHasTransitAccessAlt ( int alt ) { + int altZone = altToZone[alt]; + return tazDataManager.getHasTransitAccess(altZone); + } + + public int getTourTodOut() { + return modelStructure.getTod( tour.getTourDepartPeriod() ); + } + + public int getTourTodIn() { + return modelStructure.getTod( tour.getTourArrivePeriod() ); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getInbound", 0 ); + methodIndexMap.put( "getKidsPresent", 1 ); + methodIndexMap.put( "getTourModeIsWalk", 2 ); + methodIndexMap.put( "getTourModeIsBike", 3 ); + methodIndexMap.put( "getTourModeIsWalkLocal", 4 ); + methodIndexMap.put( "getTourModeIsWalkPremium", 5 ); + methodIndexMap.put( "getTourTodOut", 6 ); + methodIndexMap.put( "getTourTodIn", 7 ); + methodIndexMap.put( "getLnStopDcSizeAlt", 8 ); + + + methodIndexMap.put( "getTourModeIsDriveTransit", 9 ); + + + methodIndexMap.put( "getOMazDMazDistanceAlt", 20 ); + methodIndexMap.put( "getAltDMazDistanceAlt", 21 ); + + methodIndexMap.put( "getHasTransitAccessAlt", 22 ); + + } + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getInbound(); + case 1: return getKidsPresent(); + case 2: return getTourModeIsWalk(); + case 3: return getTourModeIsBike(); + case 4: return getTourModeIsWalkLocal(); + case 5: return getTourModeIsWalkPremium(); + case 6: return getTourTodOut(); + case 7: return getTourTodIn(); + case 8: return getLnStopDcSizeAlt( arrayIndex ); + + case 9: return getTourModeIsDriveTransit(); + + case 20: return getOMazDMazDistanceAlt( arrayIndex ); + case 21: return getAltDMazDistanceAlt( arrayIndex ); + + case 22: return getHasTransitAccessAlt( arrayIndex ); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapStopFrequencyDMU.java b/src/java/com/pb/cmap/tourBased/CmapStopFrequencyDMU.java new file mode 100644 index 0000000..fe840fd --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapStopFrequencyDMU.java @@ -0,0 +1,124 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.StopFrequencyDMU; +import com.pb.models.ctrampIf.TazDataIf; + + +public class CmapStopFrequencyDMU extends StopFrequencyDMU { + + TazDataIf tazDataManager; + + public CmapStopFrequencyDMU(TazDataIf tazDataManager, ModelStructure modelStructure ) { + super ( modelStructure ); + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + } + + public double getOMazDMazDistance() { + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getOriginAreaType", 0 ); + methodIndexMap.put( "getDestinationAreaType", 1 ); + methodIndexMap.put( "getIncomeInDollars", 2 ); + methodIndexMap.put( "getNumPersons", 3 ); + methodIndexMap.put( "getNumFullWork", 4 ); + methodIndexMap.put( "getNumStudent", 5 ); + methodIndexMap.put( "getNumVeh", 6 ); + methodIndexMap.put( "getCarSuff", 7 ); + methodIndexMap.put( "getNAge0to4", 8 ); + methodIndexMap.put( "getNAge5to15", 9 ); + methodIndexMap.put( "getNAdult", 10 ); + methodIndexMap.put( "getGenderIsFemale", 11 ); + methodIndexMap.put( "getStartTime", 12 ); + methodIndexMap.put( "getEndTime", 13 ); + methodIndexMap.put( "getNumAtWorkSubTours", 14 ); + methodIndexMap.put( "getNumWorkTours", 15 ); + methodIndexMap.put( "getNumUnivTours", 16 ); + methodIndexMap.put( "getNumSchoolTours", 17 ); + methodIndexMap.put( "getNumEscortTours", 18 ); + methodIndexMap.put( "getNumHShopTours", 19 ); + methodIndexMap.put( "getNumShopTours", 20 ); + methodIndexMap.put( "getNumHMaintTours", 21 ); + methodIndexMap.put( "getNumMaintTours", 22 ); + methodIndexMap.put( "getNumEatOutTours", 23 ); + methodIndexMap.put( "getNumVisitTours", 24 ); + methodIndexMap.put( "getTourIsJoint", 25 ); + methodIndexMap.put( "getTourIsVisit", 26 ); + methodIndexMap.put( "getNumPersonsInJointTour", 27 ); + methodIndexMap.put( "getJointTourHasAdultsOnly", 28 ); + methodIndexMap.put( "getTourModeIsTransit", 29 ); + methodIndexMap.put( "getTourModeIsDriveTransit", 30 ); + methodIndexMap.put( "getTourModeIsSchoolBus", 31 ); + methodIndexMap.put( "getTourModeIsNonMotorized", 32 ); + methodIndexMap.put( "getAccesibilityAtDestination", 33 ); + methodIndexMap.put( "getAccesibilityAtOrigin", 34 ); + methodIndexMap.put( "getNumStopsAlt", 35 ); + methodIndexMap.put( "getNumIbStopsAlt", 36 ); + methodIndexMap.put( "getNumObStopsAlt", 37 ); + + methodIndexMap.put( "getOMazDMazDistance", 88 ); + } + + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getOriginAreaType(); + case 1: return getDestinationAreaType(); + case 2: return getIncomeInDollars(); + case 3: return getNumPersons(); + case 4: return getNumFullWork(); + case 5: return getNumStudent(); + case 6: return getNumVeh(); + case 7: return getCarSuff(); + case 8: return getNAge0to4(); + case 9: return getNAge5to15(); + case 10: return getNAdult(); + case 11: return getGenderIsFemale(); + case 12: return getStartTime(); + case 13: return getEndTime(); + case 14: return getNumAtWorkSubTours(); + case 15: return getNumWorkTours(); + case 16: return getNumUnivTours(); + case 17: return getNumSchoolTours(); + case 18: return getNumEscortTours(); + case 19: return getNumHShopTours(); + case 20: return getNumShopTours(); + case 21: return getNumHMaintTours(); + case 22: return getNumMaintTours(); + case 23: return getNumEatOutTours(); + case 24: return getNumVisitTours(); + case 25: return getTourIsJoint(); + case 26: return getTourIsVisit(); + case 27: return getNumPersonsInJointTour(); + case 28: return getJointTourHasAdultsOnly(); + case 29: return getTourModeIsTransit(); + case 30: return getTourModeIsDriveTransit(); + case 31: return getTourModeIsSchoolBus(); + case 32: return getTourModeIsNonMotorized(); + case 33: return getAccesibilityAtDestination(); + case 34: return getAccesibilityAtOrigin(); + case 35: return getNumStopsAlt( arrayIndex ); + case 36: return getNumIbStopsAlt( arrayIndex ); + case 37: return getNumObStopsAlt( arrayIndex ); + case 88: return getOMazDMazDistance(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapStopLocationDMU.java b/src/java/com/pb/cmap/tourBased/CmapStopLocationDMU.java new file mode 100644 index 0000000..7e596ed --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapStopLocationDMU.java @@ -0,0 +1,93 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.StopLocationDMU; +import com.pb.models.ctrampIf.TazDataIf; + + +public class CmapStopLocationDMU extends StopLocationDMU { + + TazDataIf tazDataManager; + + public CmapStopLocationDMU( TazDataIf tazDataManager, ModelStructure modelStructure ) { + super ( tazDataManager, modelStructure ); + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + } + + public double getOMazDMazDistanceAlt ( int alt ) { + int destZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), destZone); + } + + public double getAltDMazDistanceAlt ( int alt ) { + int altZone = altToZone[alt]; + return tazDataManager.getOMazDMazDistance(altZone, dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getDcSoaCorrectionsAlt", 0 ); + methodIndexMap.put( "getTripModeChoiceLogsumOrigToStopAlt", 1 ); + methodIndexMap.put( "getTripModeChoiceLogsumStopAltToDest", 2 ); + methodIndexMap.put( "getStopDestAreaTypeAlt", 3 ); + methodIndexMap.put( "getStopPurposeIsWork", 4 ); + methodIndexMap.put( "getStopPurposeIsEscort", 5 ); + methodIndexMap.put( "getStopPurposeIsShopping", 6 ); + methodIndexMap.put( "getStopPurposeIsEatOut", 7 ); + methodIndexMap.put( "getStopPurposeIsOthMaint", 8 ); + methodIndexMap.put( "getStopPurposeIsSocial", 9 ); + methodIndexMap.put( "getStopPurposeIsOthDiscr", 10 ); + methodIndexMap.put( "getTourOriginZone", 11 ); + methodIndexMap.put( "getTourDestZone", 12 ); + methodIndexMap.put( "getTourMode", 13 ); + methodIndexMap.put( "getStopNumber", 14 ); + methodIndexMap.put( "getInboundStop", 15 ); + methodIndexMap.put( "getTourIsJoint", 16 ); + methodIndexMap.put( "getLnStopDcSizeAlt", 17 ); + + methodIndexMap.put( "getOMazDMazDistanceAlt", 20 ); + methodIndexMap.put( "getAltDMazDistanceAlt", 21 ); + } + + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getDcSoaCorrectionsAlt( arrayIndex ); + case 1: return getTripModeChoiceLogsumOrigToStopAlt( arrayIndex ); + case 2: return getTripModeChoiceLogsumStopAltToDest( arrayIndex ); + case 3: return getStopDestAreaTypeAlt( arrayIndex ); + case 4: return getStopPurposeIsWork(); + case 5: return getStopPurposeIsEscort(); + case 6: return getStopPurposeIsShopping(); + case 7: return getStopPurposeIsEatOut(); + case 8: return getStopPurposeIsOthMaint(); + case 9: return getStopPurposeIsSocial(); + case 10: return getStopPurposeIsOthDiscr(); + case 11: return getTourOriginZone(); + case 12: return getTourDestZone(); + case 13: return getTourMode(); + case 14: return getStopNumber(); + case 15: return getInboundStop(); + case 16: return getTourIsJoint(); + case 17: return getLnStopDcSizeAlt( arrayIndex ); + + case 20: return getOMazDMazDistanceAlt( arrayIndex ); + case 21: return getAltDMazDistanceAlt( arrayIndex ); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapTazDataHandler.java b/src/java/com/pb/cmap/tourBased/CmapTazDataHandler.java new file mode 100644 index 0000000..899f5d8 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTazDataHandler.java @@ -0,0 +1,90 @@ +package com.pb.cmap.tourBased; + + +import com.pb.models.ctrampIf.TazDataHandler; +import com.pb.common.util.ResourceUtil; + +import java.util.ResourceBundle; + +import gnu.cajo.invoke.Remote; +import gnu.cajo.utils.ItemServer; +import com.pb.cmap.tvpb.MazTapTazData; + +public class CmapTazDataHandler extends TazDataHandler { + + private static final String ZONE_DATA_AREATYPE_FIELD_NAME = "areatype"; + private static final String ZONE_DATA_DISTRICT_FIELD_NAME = "district"; + private static final String ZONE_DATA_GRADESCHOOL_DISTRICT_FIELD_NAME = "gradeschool"; + private static final String ZONE_DATA_HIGHSCHOOL_DISTRICT__FIELD_NAME = "highschool"; + + private static final int CBD_AREA_TYPE = 0; + private static final int URBAN_AREA_TYPE = 1; + private static final int SUBURBAN_AREA_TYPE = 2; + private static final int RURAL_AREA_TYPE = 3; + private static final int[][] AREA_TYPES = { {1}, {2, 3}, {4, 5, 6}, {7} }; + + public static final String ZONAL_DATA_SERVER_NAME = CmapTazDataHandler.class.getCanonicalName(); + public static final String ZONAL_DATA_SERVER_ADDRESS = "192.168.1.212"; + public static final int ZONAL_DATA_SERVER_PORT = 1138; + + private MazTapTazData mttData; + + + public CmapTazDataHandler( ResourceBundle rb, String projectDirectory, MazTapTazData mttData){ + super( rb, projectDirectory ); + + tazDataAtFieldName = ZONE_DATA_AREATYPE_FIELD_NAME; + tazDataDistFieldName = ZONE_DATA_DISTRICT_FIELD_NAME; + tazDataGradeSchoolFieldName = ZONE_DATA_GRADESCHOOL_DISTRICT_FIELD_NAME; + tazDataHighSchoolFieldName = ZONE_DATA_HIGHSCHOOL_DISTRICT__FIELD_NAME; + + cbdAreaTypesArrayIndex = CBD_AREA_TYPE; + urbanAreaTypesArrayIndex = URBAN_AREA_TYPE; + suburbanAreaTypesArrayIndex = SUBURBAN_AREA_TYPE; + ruralAreaTypesArrayIndex = RURAL_AREA_TYPE; + areaTypes = AREA_TYPES; + + setupTazDataManager(); + + //set mttData + this.mttData = mttData; + + } + + private static void usage( String[] args ) { + System.out.println( String.format( "improper arguments." ) ); + if (args.length == 0 ) { + System.out.println ( String.format( "no properties file specified." ) ); + System.out.println ( String.format( "a properties file base name (without .properties extension) must be specified as the first argument." ) ); + } + else if (args.length >= 1 ) { + System.out.println ( String.format( "improper properties file specified." ) ); + System.out.println ( String.format( "a properties file base name (without .properties extension) must be specified as the first argument." ) ); + } + } + + + public float getOMazDMazDistance(int omaz, int dmaz) { + return(mttData.getOMazDMazDistance(omaz, dmaz)); + } + + public float[] getOMazDistances(int omaz) { + return(mttData.getOMazDistances(omaz)); + } + + public float[] getAltDistances(int alt) { + return(mttData.getDMazDistances(alt)); + } + + public int getHasTransitAccess(int maz) { + return(mttData.getHasTransitAccess(maz)); + } + + public int[] getTazsForMazs() { + return (mttData.getTazsForMazs()); + } + + public MazTapTazData getMttData() { + return mttData; + } +} diff --git a/src/java/com/pb/cmap/tourBased/CmapTourBasedModel.java b/src/java/com/pb/cmap/tourBased/CmapTourBasedModel.java new file mode 100644 index 0000000..dedeb51 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTourBasedModel.java @@ -0,0 +1,301 @@ +package com.pb.cmap.tourBased; + + +import java.util.HashMap; +import java.util.ResourceBundle; +import java.util.MissingResourceException; + +import org.apache.log4j.Logger; + +import com.pb.cmap.synpop.ARCPopulationSynthesizer; +import com.pb.cmap.tvpb.TransitVirtualPathBuilder; +import com.pb.common.util.ResourceUtil; +import com.pb.models.ctrampIf.HouseholdDataManager; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.HouseholdDataManagerRmi; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.jppf.CtrampApplication; + +public class CmapTourBasedModel { + + private static Logger logger = Logger.getLogger(CmapTourBasedModel.class); + + public static final String PROPERTIES_PROJECT_DIRECTORY = "Project.Directory"; + + private static final int DEFAULT_ITERATION_NUMBER = 1; + private static final float DEFAULT_SAMPLE_RATE = 1.0f; + private static final int DEFAULT_SAMPLE_SEED = 0; + + public static final int DEBUG_CHOICE_MODEL_HHID = 740151; + + private ResourceBundle rb; + private String propertiesFileBaseName; + + // values for these variables are set as command line arguments, or default vaues are used if no command line arguments are specified. + private int globalIterationNumber = 0; + private float iterationSampleRate = 0f; + private int sampleSeed = 0; + + + /** + * + * @param rb, java.util.ResourceBundle containing environment settings from a properties file specified on the command line + * @param baseName, String containing basename (without .properites) from which ResourceBundle was created. + * @param globalIterationNumber, int iteration number for which the model is run, set by another process controlling a model stream with feedback. + * @param iterationSampleRate, float percentage [0.0, 1.0] inicating the portion of all households to be modeled. + * + * This object defines the implementation of the ARC tour based, activity based travel demand model. + */ + public CmapTourBasedModel( ResourceBundle rb, String baseName, int globalIterationNumber, float iterationSampleRate, int sampleSeed ) { + this.rb = rb; + propertiesFileBaseName = baseName; + this.globalIterationNumber = globalIterationNumber; + this.iterationSampleRate = iterationSampleRate; + this.sampleSeed = sampleSeed; + } + + + + private void runTourBasedModel() { + + + // new a ctramp application object + CmapCtrampApplication ctrampApplication = new CmapCtrampApplication( rb ); + String projectDirectory = ctrampApplication.getProjectDirectoryName(); + + // create modelStructure object + CmapModelStructure modelStructure = new CmapModelStructure(); + + + + boolean localHandlers = false; + + String hhHandlerAddress = ""; + int hhServerPort = 0; + try { + // get household server address. if none is specified a local server in the current process will be started. + hhHandlerAddress = rb.getString( "RunModel.HouseholdServerAddress" ); + try { + // get household server port. + hhServerPort = Integer.parseInt( rb.getString( "RunModel.HouseholdServerPort" ) ); + localHandlers = false; + } + catch ( MissingResourceException e ) { + // if no household data server address entry is found, the object will be created in the local process + localHandlers = true; + } + } + catch ( MissingResourceException e ) { + localHandlers = true; + } + + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(rb); + + //create TVPB in order to get mttData (maz, tap, taz) data manager + TransitVirtualPathBuilder tvpb = new TransitVirtualPathBuilder(propertyMap); + tvpb.setupTVPB(); + tvpb.createMazTapTazData(); + + //create zone data manager and add mttData + TazDataIf tazDataHandler; + tazDataHandler = new CmapTazDataHandler(rb, projectDirectory, tvpb.getMTTData()); + logger.info ( "Check getOMazDMazDistance(1,2): " + tazDataHandler.getOMazDMazDistance(1, 2)); + logger.info ( "Check getOMazDMazDistance(1,1000): " + tazDataHandler.getOMazDMazDistance(1, 1000)); + + // setup the ctramp application + ctrampApplication.setupModels( modelStructure, tazDataHandler ); + + // generate the synthetic population + ARCPopulationSynthesizer populationSynthesizer = new ARCPopulationSynthesizer( propertiesFileBaseName ); + ctrampApplication.runPopulationSynthesizer( populationSynthesizer ); + + HouseholdDataManagerIf householdDataManager; + String testString; + try { + + if ( localHandlers ) { + + // create a new local instance of the household array manager + householdDataManager = new CmapHouseholdDataManager(); + householdDataManager.setPropertyFileValues( propertyMap ); + + // have the household data manager read the synthetic population files and apply its tables to objects mapping method. + String inputHouseholdFileName = rb.getString( HouseholdDataManager.PROPERTIES_SYNPOP_INPUT_HH ); + String inputPersonFileName = rb.getString( HouseholdDataManager.PROPERTIES_SYNPOP_INPUT_PERS ); + householdDataManager.setHouseholdSampleRate( iterationSampleRate, sampleSeed ); + householdDataManager.setupHouseholdDataManager( modelStructure, tazDataHandler, inputHouseholdFileName, inputPersonFileName ); + + } + else { + + householdDataManager = new HouseholdDataManagerRmi( hhHandlerAddress, hhServerPort, CmapHouseholdDataManager.HH_DATA_SERVER_NAME ); + testString = householdDataManager.testRemote(); + logger.info ( "HouseholdDataManager test: " + testString ); + + householdDataManager.setPropertyFileValues( propertyMap ); + + + // have the household data manager read the synthetic population files and apply its tables to objects mapping method. + boolean restartHhServer = false; + try { + // possible values for the following can be none, ao, cdap, imtf, imtod, awf, awl, awtod, jtf, jtl, jtod, inmtf, inmtl, inmtod, stf, stl + String restartModel = rb.getString( "RunModel.RestartWithHhServer" ); + if ( restartModel.equalsIgnoreCase("none") ) + restartHhServer = true; + else if ( restartModel.equalsIgnoreCase("uwsl") || restartModel.equalsIgnoreCase("ao") || + restartModel.equalsIgnoreCase("fp") || restartModel.equalsIgnoreCase("cdap") || restartModel.equalsIgnoreCase("imtf") || + restartModel.equalsIgnoreCase("imtod") || restartModel.equalsIgnoreCase("awf") || restartModel.equalsIgnoreCase("awl") || + restartModel.equalsIgnoreCase("awtod") || restartModel.equalsIgnoreCase("jtf") || restartModel.equalsIgnoreCase("jtl") || + restartModel.equalsIgnoreCase("jtod") || restartModel.equalsIgnoreCase("inmtf") || restartModel.equalsIgnoreCase("inmtl") || + restartModel.equalsIgnoreCase("inmtod") || restartModel.equalsIgnoreCase("stf") || restartModel.equalsIgnoreCase("stl") ) + restartHhServer = false; + } + catch ( MissingResourceException e ) { + restartHhServer = true; + } + + + + if ( restartHhServer ) { + + householdDataManager.setDebugHhIdsFromHashmap (); + + String inputHouseholdFileName = rb.getString( HouseholdDataManager.PROPERTIES_SYNPOP_INPUT_HH ); + String inputPersonFileName = rb.getString( HouseholdDataManager.PROPERTIES_SYNPOP_INPUT_PERS ); + householdDataManager.setHouseholdSampleRate( iterationSampleRate, sampleSeed ); + householdDataManager.mapTablesToHouseholdObjects(inputHouseholdFileName, inputPersonFileName, modelStructure, tazDataHandler); + + } + else { + + // if the restart is from a disk object file, the ctrampApplication.runModels() method will take care of readig the file + // and the debug households already set will be used. + if ( ctrampApplication.restartFromDiskObjectFile() == false ) { + householdDataManager.setHouseholdSampleRate( iterationSampleRate, sampleSeed ); + householdDataManager.setDebugHhIdsFromHashmap (); + householdDataManager.setTraceHouseholdSet(); + + // set the random number sequence for household objects accordingly based on which model components are + // assumed to have already run and are stored in the remote HouseholdDataManager object. + ctrampApplication.restartModels( householdDataManager ); + } + + } + + } + + + + // create a factory object to pass to various model components from which they can create DMU objects + CmapCtrampDmuFactory dmuFactory = new CmapCtrampDmuFactory( tazDataHandler, modelStructure ); + + //create trip matrix writer + CmapTripMatrixWriter tripMatrixWriter = new CmapTripMatrixWriter(rb, householdDataManager, tazDataHandler, globalIterationNumber, iterationSampleRate); + + // run the models + ctrampApplication.runModels( householdDataManager, dmuFactory, globalIterationNumber, tripMatrixWriter); + + + } + catch ( Exception e ) { + + logger.error ( String.format( "exception caught running ctramp model components -- exiting." ), e ); + throw new RuntimeException(); + + } + + } + + + + public static void main(String[] args) { + + long startTime = System.currentTimeMillis(); + int globalIterationNumber = -1; + float iterationSampleRate = -1.0f; + int sampleSeed = -1; + + ResourceBundle rb = null; + + logger.info( String.format( "CMAP Tour Based Model using CT-RAMP version %s", CtrampApplication.VERSION ) ); + + if ( args.length == 0 ) { + logger.error( String.format( "no properties file base name (without .properties extension) was specified as an argument." ) ); + return; + } + else { + rb = ResourceBundle.getBundle( args[0] ); + + // optional arguments + for (int i=1; i < args.length; i++) { + + if (args[i].equalsIgnoreCase("-iteration")) { + globalIterationNumber = Integer.parseInt( args[i+1] ); + logger.info( String.format( "-iteration %d.", globalIterationNumber ) ); + } + + if (args[i].equalsIgnoreCase("-sampleRate")) { + iterationSampleRate = Float.parseFloat( args[i+1] ); + logger.info( String.format( "-sampleRate %.4f.", iterationSampleRate ) ); + } + + if (args[i].equalsIgnoreCase("-sampleSeed")) { + sampleSeed = Integer.parseInt( args[i+1] ); + logger.info( String.format( "-sampleSeed %d.", sampleSeed ) ); + } + + } + + if ( globalIterationNumber < 0 ) { + globalIterationNumber = DEFAULT_ITERATION_NUMBER; + logger.info( String.format( "no -iteration flag, default value %d used.", globalIterationNumber ) ); + } + + if ( iterationSampleRate < 0 ) { + iterationSampleRate = DEFAULT_SAMPLE_RATE; + logger.info( String.format( "no -sampleRate flag, default value %.4f used.", iterationSampleRate ) ); + } + + if ( sampleSeed < 0 ) { + sampleSeed = DEFAULT_SAMPLE_SEED; + logger.info( String.format( "no -sampleSeed flag, default value %d used.", sampleSeed ) ); + } + + } + + + String baseName; + if ( args[0].endsWith(".properties") ) { + int index = args[0].indexOf(".properties"); + baseName = args[0].substring(0, index); + } + else { + baseName = args[0]; + } + + + + + // create an instance of this class for main() to use. + CmapTourBasedModel mainObject = new CmapTourBasedModel( rb, baseName, globalIterationNumber, iterationSampleRate, sampleSeed ); + + // run tour based models + try { + + logger.info (""); + logger.info ("starting tour based model."); + mainObject.runTourBasedModel(); + + } + catch (RuntimeException e) { + logger.error ( "RuntimeException caught in com.pb.cmap.tourBased.TourBasedModel.main() -- exiting.", e ); + } + + logger.info (""); + logger.info (""); + logger.info ("CMAP Tour Based Model finished in " + ((System.currentTimeMillis() - startTime) / 60000.0) + " minutes."); + + System.exit(0); + } + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapTourDepartureTimeAndDurationDMU.java b/src/java/com/pb/cmap/tourBased/CmapTourDepartureTimeAndDurationDMU.java new file mode 100644 index 0000000..cbb6519 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTourDepartureTimeAndDurationDMU.java @@ -0,0 +1,383 @@ +/* + * Copyright 2005 PB Consult Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourDepartureTimeAndDurationDMU; +import com.pb.models.ctrampIf.TourIf; + +/** + * ArcTourDepartureTimeAndDurationDMU is a class that ... + * + * @author Kimberly Grommes + * @version 1.0, Jul 17, 2008 + * Created by IntelliJ IDEA. + */ +public class CmapTourDepartureTimeAndDurationDMU extends TourDepartureTimeAndDurationDMU { + + TazDataIf tazDataManager; + + public CmapTourDepartureTimeAndDurationDMU(TazDataIf tazDataManager, ModelStructure modelStructure ){ + super( modelStructure ); + setupMethodIndexMap(); + + this.tazDataManager = tazDataManager; + + } + + + public int getIncomeLessThan30k() + { + float incomeInDollars = (float) household.getIncomeInDollars(); + return (incomeInDollars < 30000) ? 1 : 0; + } + + public int getIncome30kTo60k() + { + float incomeInDollars = (float) household.getIncomeInDollars(); + return (incomeInDollars >= 30000 && incomeInDollars < 60000) ? 1 : 0; + } + + public int getIncomeHigherThan100k() + { + float incomeInDollars = (float) household.getIncomeInDollars(); + return (incomeInDollars >= 100000) ? 1 : 0; + } + + public float getIncome() { + return household.getIncomeSegment(); + } + + public int getAge() + { + return getPersonAge(); + } + + public int getFemale() + { + return getPersonIsFemale(); + } + + public int getFemaleWithPreschooler() + { + return ((getPersonIsFemale() == 1) && (getNumPreschoolChildrenInHh() > 1)) ? 1 : 0; + } + + public int getDrivingAgeStudent() + { + return (getStudentDrivingAge() == 1) ? 1 : 0; + } + + public int getSchoolChildWithMandatoryTour() + { + return ( getStudentNonDrivingAge() == 1 && getPersonMandatoryTotal() > 0 ) ? 1 : 0; + } + + public int getUniversityWithMandatoryPattern() + { + return ( getUniversityStudent() == 1 && person.getCdapActivity().equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN )) ? 1 : 0; + } + + public int getWorkerWithMandatoryPattern() + { + return ( (getFullTimeWorker() == 1 || getPartTimeWorker() ==1) && person.getCdapActivity().equalsIgnoreCase(ModelStructure.MANDATORY_PATTERN )) ? 1 : 0; + } + + public int getPreschoolChildWithMandatoryTour() + { + return ( getPreschool() == 1 && getPersonMandatoryTotal() > 0 ) ? 1 : 0; + } + + public int getNonWorkerInHH() + { + return (getNumNonWorkingAdultsInHh() > 0) ? 1 : 0; + } + + public int getJointTour() + { + return (tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) ? 1 : 0; + } + + public int getIndividualTour() + { + return (tour.getTourCategory().equalsIgnoreCase(ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY)) ? 1 : 0; + } + + public int getJointTourInHH() + { + return (getHhJointTotal() > 0) ? 1 : 0; + } + + public int getSubsequentTourIsWorkTour() + { + return subsequentTourIsWork; + } + + public int getSubsequentTourIsSchoolTour() + { + return subsequentTourIsSchool; + } + + public int getNumberOfNonEscortingIndividualTours() + { + return getPersonNonMandatoryTotalNoEscort(); + } + + public int getNumberOfDiscretionaryTours() + { + return getPersonJointAndIndivDiscrToursTotal(); + } + + public double getOMazDMazDistance() { + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap() + { + methodIndexMap = new HashMap(); + + methodIndexMap.put("getDestinationEmploymentDensity", 1); + methodIndexMap.put("getIncomeLessThan30k", 2); + methodIndexMap.put("getIncome30kTo60k", 3); + methodIndexMap.put("getIncomeHigherThan100k", 4); + methodIndexMap.put("getAge", 5); + methodIndexMap.put("getFemale", 6); + methodIndexMap.put("getFemaleWithPreschooler", 7); + methodIndexMap.put("getFullTimeWorker", 8); + methodIndexMap.put("getPartTimeWorker", 9); + methodIndexMap.put("getUniversityStudent", 10); + methodIndexMap.put("getDrivingAgeStudent", 11); + methodIndexMap.put("getNonWorkerInHH", 12); + methodIndexMap.put("getJointTourInHH", 13); + methodIndexMap.put("getFirstTour", 14); + methodIndexMap.put("getSubsequentTour", 15); + methodIndexMap.put("getModeChoiceLogsumAlt", 16); + methodIndexMap.put("getSubsequentTourIsWorkTour", 17); + methodIndexMap.put("getSubsequentTourIsSchoolTour", 18); + methodIndexMap.put("getEndOfPreviousTour", 19); + methodIndexMap.put("getAllAdultsFullTimeWorkers", 20); + methodIndexMap.put("getNonWorker", 21); + methodIndexMap.put("getRetired", 22); + methodIndexMap.put("getSchoolChildWithMandatoryTour", 23); + methodIndexMap.put("getPreschoolChildWithMandatoryTour", 24); + methodIndexMap.put("getNumberOfNonEscortingIndividualTours", 25); + methodIndexMap.put("getNumberOfDiscretionaryTours", 26); + methodIndexMap.put("getIndividualTour", 27); + methodIndexMap.put("getJointTour", 28); + methodIndexMap.put("getHouseholdSize", 29); + methodIndexMap.put("getKidsOnJointTour", 30); + methodIndexMap.put("getAdditionalShoppingTours", 31); + methodIndexMap.put("getAdditionalMaintenanceTours", 32); + methodIndexMap.put("getAdditionalVisitingTours", 33); + methodIndexMap.put("getAdditionalDiscretionaryTours", 34); + methodIndexMap.put("getMaximumAvailableTimeWindow", 35); + methodIndexMap.put("getWorkerWithMandatoryPattern", 36); + methodIndexMap.put("getUnivStudentWithMandatoryPattern", 37); + methodIndexMap.put("getHhChildUnder16", 38); + methodIndexMap.put("getToursLeftToSchedule", 39); + methodIndexMap.put("getPreDrivingAgeChild", 40); + methodIndexMap.put("getJointTourPartySize", 41); + methodIndexMap.put("getSubtourPurposeIsEatOut", 42); + methodIndexMap.put("getSubtourPurposeIsBusiness", 43); + methodIndexMap.put("getSubtourPurposeIsOther", 44); + methodIndexMap.put("getMaxJointTimeWindow", 45); + methodIndexMap.put("getOriginAreaType", 46); + methodIndexMap.put("getDestinationAreaType", 47); + methodIndexMap.put("getNumPreschoolChildrenInHh", 48); + methodIndexMap.put("getPersonType", 49); + methodIndexMap.put("getIncome", 50); + + methodIndexMap.put( "getOMazDMazDistance", 88 ); + + } + + public double getValueForIndex(int variableIndex, int arrayIndex) + { + + double returnValue = -1; + + switch (variableIndex) + { + case 1: + returnValue = 0; + break; + case 2: + returnValue = getIncomeLessThan30k(); + break; + case 3: + returnValue = getIncome30kTo60k(); + break; + case 4: + returnValue = getIncomeHigherThan100k(); + break; + case 5: + returnValue = getAge(); + break; + case 6: + returnValue = getFemale(); + break; + case 7: + returnValue = getFemaleWithPreschooler(); + break; + case 8: + returnValue = getFullTimeWorker(); + break; + case 9: + returnValue = getPartTimeWorker(); + break; + case 10: + returnValue = getUniversityStudent(); + break; + case 11: + returnValue = getDrivingAgeStudent(); + break; + case 12: + returnValue = getNonWorkerInHH(); + break; + case 13: + returnValue = getJointTourInHH(); + break; + case 14: + returnValue = getFirstTour(); + break; + case 15: + returnValue = getSubsequentTour(); + break; + case 16: + returnValue = getModeChoiceLogsumAlt(arrayIndex); + break; + case 17: + returnValue = getSubsequentTourIsWorkTour(); + break; + case 18: + returnValue = getSubsequentTourIsSchoolTour(); + break; + case 19: + returnValue = getEndOfPreviousTour(); + break; + case 20: + returnValue = getAllAdultsFullTimeWorkers(); + break; + case 21: + returnValue = getNonWorker(); + break; + case 22: + returnValue = getRetired(); + break; + case 23: + returnValue = getSchoolChildWithMandatoryTour(); + break; + case 24: + returnValue = getPreschoolChildWithMandatoryTour(); + break; + case 25: + returnValue = getNumberOfNonEscortingIndividualTours(); + break; + case 26: + returnValue = getNumberOfDiscretionaryTours(); + break; + case 27: + returnValue = getIndividualTour(); + break; + case 28: + returnValue = getJointTour(); + break; + case 29: + returnValue = getHouseholdSize(); + break; + case 30: + returnValue = getKidsOnJointTour(); + break; + case 31: + returnValue = getNumIndivShopTours() - 1; + break; + case 32: + returnValue = getNumIndivMaintTours() - 1; + break; + case 33: + returnValue = getNumIndivVisitTours() - 1; + break; + case 34: + returnValue = getNumIndivDiscrTours() - 1; + break; + case 35: + returnValue = getMaximumAvailableTimeWindow(); + break; + case 36: + returnValue = getWorkerWithMandatoryPattern(); + break; + case 37: + returnValue = getUniversityWithMandatoryPattern(); + break; + case 38: + returnValue = getNumChildrenUnder16InHh() > 0 ? 1 : 0; + break; + case 39: + returnValue = getToursLeftToSchedule(); + break; + case 40: + returnValue = getPreDrivingAgeChild(); + break; + case 41: + returnValue = getJointTourPartySize(); + break; + case 42: + returnValue = getSubtourPurposeIsEatOut(); + break; + case 43: + returnValue = getSubtourPurposeIsBusiness(); + break; + case 44: + returnValue = getSubtourPurposeIsOther(); + break; + case 45: + returnValue = getMaxJointTimeWindow( tour ); + break; + case 46: + returnValue = getOriginAreaType(); + break; + case 47: + returnValue = getDestinationAreaType(); + break; + case 48: + returnValue = getNumPreschoolChildrenInHh(); + break; + case 49: + returnValue = getPersonType(); + break; + case 50: + returnValue = getIncome(); + break; + case 88: + returnValue = getOMazDMazDistance(); + break; + + + default: + logger.error("method number = " + variableIndex + " not found"); + throw new RuntimeException("method number = " + variableIndex + " not found"); + + } + + return returnValue; + + } + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapTourModeChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapTourModeChoiceDMU.java new file mode 100644 index 0000000..16a011a --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTourModeChoiceDMU.java @@ -0,0 +1,371 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.cmap.tourBased.CmapModelStructure; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.TazDataIf; + + + +public class CmapTourModeChoiceDMU extends TourModeChoiceDMU { + + int[] zoneTableRow; + int[] areaType; + float[] prkCost; + float[] bhhden; + float[] bempden; + float[] pef; + int[] ring; + CmapModelStructure modelStructure; + + int[] tazForMaz; + + TazDataIf tazDataManager; + + public CmapTourModeChoiceDMU(TazDataIf tazDataManager, CmapModelStructure modelStructure){ + super( modelStructure ); + this.modelStructure = modelStructure; + setup( tazDataManager ); + setupMethodIndexMap(); + } + + private void setup( TazDataIf tazDataManager ) { + + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + bhhden = tazDataManager.getBHHDen(); + bempden = tazDataManager.getBEmpDen(); + pef = tazDataManager.getPef(); + ring = tazDataManager.getRing(); + prkCost = tazDataManager.getZonalParkRate(); + + tazForMaz = tazDataManager.getTazsForMazs(); + + this.tazDataManager = tazDataManager; + + } + + public double getOriginBHHDen() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return bhhden[index]; + } + + public double getDestinationBHHDen() { + int index = zoneTableRow[dmuIndex.getDestZone()] - 1; + return bhhden[index]; + } + + public double getOrigRing() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return ring[index]; + } + + public double getDestRing() { + int index = zoneTableRow[dmuIndex.getDestZone()] - 1; + return ring[index]; + } + + public double getOriginBEmpDen() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return bempden[index]; + } + + public double getDestinationBEmpDen() { + int index = zoneTableRow[dmuIndex.getDestZone()] - 1; + return bempden[index]; + } + + public double getOriginPef() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return pef[index]; + } + + public double getDestinationPef() { + int index = zoneTableRow[dmuIndex.getDestZone()] - 1; + return pef[index]; + } + + public double getOrigParkCost() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return prkCost[index]; + } + + public double getDestParkCost() { + int index = zoneTableRow[dmuIndex.getDestZone()] - 1; + return prkCost[index]; + } + + + /** + * get skim period for tour departure interval + */ + public int getTodOut() { + return modelStructure.getTod( tour.getTourDepartPeriod() ); + } + + /** + * get skim period for tour arrival interval + */ + public int getTodIn() { + return modelStructure.getTod( tour.getTourArrivePeriod() ); + } + + public int getZonalShortWalkAccessOrig() { + if ( tour.getTourOrigWalkSubzone() == 1 ) + return 1; + else + return 0; + } + + public int getZonalShortWalkAccessDest() { + if ( tour.getTourDestWalkSubzone() == 1 ) + return 1; + else + return 0; + } + + public int getZonalLongWalkAccessOrig() { + if ( tour.getTourOrigWalkSubzone() == 2 ) + return 1; + else + return 0; + } + + public int getZonalLongWalkAccessDest() { + if ( tour.getTourDestWalkSubzone() == 2 ) + return 1; + else + return 0; + } + + // fixed Structure value -- need to update to use ModelStructure + // TODO update to make general using ModelStructure and remove zdm + public int getRuralDestination() { + + //TODO: Kim review with Jim. + //int at = tazDataManager.getZonalAreaType( tour.getTourDestTaz() ); + int at = areaType[tour.getTourDestTaz() - 1]; + + if ( at == 7 ) // Structure.AreaType.RURAL.ordinal() ) + return 1; + else + return 0; + } + + + + public int getIncome() { + return hh.getIncomeSegment(); + } + + + public int getOmazOtaz() { + return tazForMaz[dmuIndex.getOriginZone()-1]; + } + + public int getDmazDtaz() { + return tazForMaz[dmuIndex.getDestZone()-1]; + } + + public double getOMazDMazDistance() { + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getTodOut", 0 ); + methodIndexMap.put( "getTodIn", 1 ); + methodIndexMap.put( "getZonalShortWalkAccessOrig", 2 ); + methodIndexMap.put( "getZonalShortWalkAccessDest", 3 ); + methodIndexMap.put( "getZonalLongWalkAccessOrig", 4 ); + methodIndexMap.put( "getZonalLongWalkAccessDest", 5 ); + methodIndexMap.put( "getRuralDestination", 6 ); + methodIndexMap.put( "getHhSize", 7 ); + methodIndexMap.put( "getAutos", 8 ); + methodIndexMap.put( "getDrivers", 9 ); + methodIndexMap.put( "getAge", 10 ); + methodIndexMap.put( "getIncome", 11 ); + methodIndexMap.put( "getAgeUnder40", 12 ); + methodIndexMap.put( "getAge40to59", 13 ); + methodIndexMap.put( "getAge60to79", 14 ); + methodIndexMap.put( "getAge60plus", 15 ); + methodIndexMap.put( "getPersonIsWorker", 16 ); + methodIndexMap.put( "getPersonIsNonWorkingAdult", 17 ); + methodIndexMap.put( "getPersonIsMale", 18 ); + methodIndexMap.put( "getPreDrivingChildInHh", 19 ); + methodIndexMap.put( "getNumFemalesInHh", 20 ); + methodIndexMap.put( "getFreeParking", 23 ); + methodIndexMap.put( "getHomemaker", 24 ); + methodIndexMap.put( "getWorkers", 25 ); + methodIndexMap.put( "getSize", 26 ); + methodIndexMap.put( "getGender", 27 ); + methodIndexMap.put( "getChildunder16", 28 ); + methodIndexMap.put( "getChild16plus", 29 ); + methodIndexMap.put( "getTourCategoryJoint", 30 ); + methodIndexMap.put( "getTourPurposeEscort", 31 ); + methodIndexMap.put( "getTourPurposeShopping", 32 ); + methodIndexMap.put( "getTourPurposeEatOut", 33 ); + methodIndexMap.put( "getTourPurposeSocial", 34 ); + methodIndexMap.put( "getTourPurposeOthDiscr", 35 ); + methodIndexMap.put( "getNumberOfParticipantsInJointTour", 36 ); + methodIndexMap.put( "getWorkTourModeIsSOV", 37 ); + methodIndexMap.put( "getWorkTourModeIsBike", 38 ); + methodIndexMap.put( "getSubtourType", 39 ); + methodIndexMap.put( "getTourDepartsAfter4pm", 40 ); + methodIndexMap.put( "getTourArrivesAfter7pm", 41 ); + methodIndexMap.put( "getValueOfTime", 42 ); + + methodIndexMap.put( "getOriginBHHDen", 43 ); + methodIndexMap.put( "getDestinationBHHDen", 44 ); + methodIndexMap.put( "getOriginBEmpDen", 45 ); + methodIndexMap.put( "getDestinationBEmpDen", 46 ); + methodIndexMap.put( "getOriginPef", 47 ); + methodIndexMap.put( "getDestinationPef", 48 ); + + methodIndexMap.put( "getPersonIsPartTimeWorker", 49); + methodIndexMap.put( "getNumChildrenUnder19", 50); + methodIndexMap.put( "getNumPreschool", 51); + methodIndexMap.put( "getNumPersons6to15", 52); + methodIndexMap.put( "getWorkTourMode", 53); + methodIndexMap.put( "getNumChildren", 54); + methodIndexMap.put( "getHouseholdMaxValueOfTime", 55); + + methodIndexMap.put( "getOrigRing", 56 ); + methodIndexMap.put( "getDestRing", 57 ); + + methodIndexMap.put( "getOrigParkCost", 58 ); + methodIndexMap.put( "getDestParkCost", 59 ); + + methodIndexMap.put( "getOmazOtaz", 60 ); + methodIndexMap.put( "getDmazDtaz", 61 ); + + methodIndexMap.put( "getGenCostWT_In", 70 ); + methodIndexMap.put( "getGenCostDL_In", 71 ); + methodIndexMap.put( "getGenCostDP_In", 72 ); + methodIndexMap.put( "getOtapWT_In", 73 ); + methodIndexMap.put( "getDtapWT_In", 74 ); + methodIndexMap.put( "getOtapDL_In", 75 ); + methodIndexMap.put( "getDtapDL_In", 76 ); + methodIndexMap.put( "getOtapDP_In", 77 ); + methodIndexMap.put( "getDtapDP_In", 78 ); + + methodIndexMap.put( "getGenCostWT_Out", 80 ); + methodIndexMap.put( "getGenCostDL_Out", 81 ); + methodIndexMap.put( "getGenCostDP_Out", 82 ); + methodIndexMap.put( "getOtapWT_Out", 83 ); + methodIndexMap.put( "getDtapWT_Out", 84 ); + methodIndexMap.put( "getOtapDL_Out", 85 ); + methodIndexMap.put( "getDtapDL_Out", 86 ); + methodIndexMap.put( "getOtapDP_Out", 87 ); + methodIndexMap.put( "getDtapDP_Out", 88 ); + + methodIndexMap.put( "getOMazDMazDistance", 90 ); + + } + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getTodOut(); + case 1: return getTodIn(); + case 2: return getZonalShortWalkAccessOrig(); + case 3: return getZonalShortWalkAccessDest(); + case 4: return getZonalLongWalkAccessOrig(); + case 5: return getZonalLongWalkAccessDest(); + case 6: return getRuralDestination(); + case 7: return getHhSize(); + case 8: return getAutos(); + case 9: return getDrivers(); + case 10: return getAge(); + case 11: return getIncome(); + case 12: return getAgeUnder40(); + case 13: return getAge40to59(); + case 14: return getAge60to79(); + case 15: return getAge60plus(); + case 16: return getPersonIsWorker(); + case 17: return getPersonIsNonWorkingAdult(); + case 18: return getPersonIsMale(); + case 19: return getPreDrivingChildInHh(); + case 20: return getNumFemalesInHh(); + case 23: return getFreeParking(); + case 24: return getHomemaker(); + case 25: return getWorkers(); + case 26: return getSize(); + case 27: return getGender(); + case 28: return getChildunder16(); + case 29: return getChild16plus(); + case 30: return getTourCategoryJoint(); + case 31: return getTourPrimaryPurposeEscort(); + case 32: return getTourPrimaryPurposeShopping(); + case 33: return getTourPrimaryPurposeEatOut(); + case 34: return getTourPrimaryPurposeSocial(); + case 35: return getTourPrimaryPurposeOthDiscr(); + case 36: return getNumberOfParticipantsInJointTour(); + case 37: return getWorkTourModeIsSOV(); + case 38: return getWorkTourModeIsBike(); + case 39: return getSubtourType(); + case 40: return getTourDepartsAfter4pm(); + case 41: return getTourArrivesAfter7pm(); + case 42: return getValueOfTime(); + + case 43: return getOriginBHHDen(); + case 44: return getDestinationBHHDen(); + case 45: return getOriginBEmpDen(); + case 46: return getDestinationBEmpDen(); + case 47: return getOriginPef(); + case 48: return getDestinationPef(); + + case 49: return getPersonIsPartTimeWorker(); + case 50: return getNumChildrenUnder19(); + case 51: return getNumPreschool(); + case 52: return getNumPersons6to15(); + case 53: return getWorkTourMode(); + case 54: return getNumChildren(); + case 55: return getHouseholdMaxValueOfTime(); + + case 56: return getOrigRing(); + case 57: return getDestRing(); + + case 58: return getOrigParkCost(); + case 59: return getDestParkCost(); + + case 60: return getOmazOtaz(); + case 61: return getDmazDtaz(); + + case 70: return getGenCostWT_In(); + case 71: return getGenCostDL_In(); + case 72: return getGenCostDP_In(); + case 73: return getOtapWT_In(); + case 74: return getDtapWT_In(); + case 75: return getOtapDL_In(); + case 76: return getDtapDL_In(); + case 77: return getOtapDP_In(); + case 78: return getDtapDP_In(); + + case 80: return getGenCostWT_Out(); + case 81: return getGenCostDL_Out(); + case 82: return getGenCostDP_Out(); + case 83: return getOtapWT_Out(); + case 84: return getDtapWT_Out(); + case 85: return getOtapDL_Out(); + case 86: return getDtapDL_Out(); + case 87: return getOtapDP_Out(); + case 88: return getDtapDP_Out(); + + case 90: return getOMazDMazDistance(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tourBased/CmapTripMatrixWriter.java b/src/java/com/pb/cmap/tourBased/CmapTripMatrixWriter.java new file mode 100644 index 0000000..a00c671 --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTripMatrixWriter.java @@ -0,0 +1,651 @@ +package com.pb.cmap.tourBased; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import org.apache.log4j.Logger; + +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.matrix.Matrix; +import com.pb.common.matrix.MatrixType; +import com.pb.common.matrix.MatrixWriter; +import com.pb.common.util.ResourceUtil; + +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TripMatrixWriterIf; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; + +/** Calculate and write trip matrices to EMME + * @author bts + */ +public class CmapTripMatrixWriter implements TripMatrixWriterIf { + + private transient Logger logger = Logger.getLogger(CmapTripMatrixWriter.class); + + private static final String PROPERTIES_INDIV_TRIP_DATA_FILE = "Results.IndivTripDataFile"; + private static final String PROPERTIES_JOINT_TRIP_DATA_FILE = "Results.JointTripDataFile"; + + private static final String PROPERTIES_PROJECT_DIRECTORY = "Project.Directory"; + private static final String PROPERTIES_LOWVOT_UPPERBOUND = "Results.TripMatrices.LowVOTUpperBound"; + private static final String PROPERTIES_NUMZONES = "Results.TripMatrices.NumZones"; + private static final String PROPERTIES_FOLDER = "Results.TripMatrices.Folder"; + private static final String PROPERTIES_TIMEPERIOD_UPPERBOUNDS = "Results.TripMatrices.TimePeriodUpperBounds"; + private static final String PROPERTIES_TRIPMATRICES_NUMBERS = "Results.TripMatrices.Numbers"; + private static final String PROPERTIES_TRIPMATRICES_NAMES = "Results.TripMatrices.Names"; + private static final String PROPERTIES_TRANSITMATRICES_NUMBERS = "Results.TripMatrices.TransitNumbers"; + private static final String PROPERTIES_TRANSITMATRICES_NAMES = "Results.TripMatrices.TransitNames"; + private static final String PROPERTIES_NUMTRANSITZONES = "Results.TripMatrices.NumTransitZones"; + + private static final float hov2occupancy = 2.0f; + private static final float hov3occupancy = 3.3f; + + //mode choice alt codes + private static final int tripModeCode_DRIVEALONEFREE = 1; + private static final int tripModeCode_DRIVEALONEPAY = 2; + private static final int tripModeCode_SHARED2FREE = 3; + private static final int tripModeCode_SHARED2PAY = 4; + private static final int tripModeCode_SHARED3FREE = 5; + private static final int tripModeCode_SHARED3PAY = 6; + + private static final int tripModeCode_WALK_LOCAL = 9; + private static final int tripModeCode_WALK_PREMIUM = 10; + private static final int tripModeCode_DRIVE_LOCAL = 11; + private static final int tripModeCode_DRIVE_PREMIUM = 12; + + private ResourceBundle resourceBundle; + private HouseholdDataManagerIf householdDataManager; + private int iteration; + private float iterationSampleRate; + private TableDataSet indivTrips; + private TableDataSet jointTrips; + private float lowVOTUpperBound; + private int numZones; + private int numTransitZones; + private String folder; + private int[] timePeriodUpperBounds; + private String[] matrixNums; + private String[] matrixNames; + private Matrix[] matrices; + + private HashMap vots; + private HashMap oldestPersonId; + private HashMap user_class_work_walk; + private HashMap user_class_work_pnr; + private HashMap user_class_work_knr; + private HashMap user_class_non_work_walk; + private HashMap user_class_non_work_pnr; + private HashMap user_class_non_work_knr; + + private String[] transitMatrixNums; + private String[] transitMatrixNames; + private Matrix[] transitMatrices; + + TazDataIf tazDataHandler; + + public CmapTripMatrixWriter( ResourceBundle resourceBundle, HouseholdDataManagerIf householdDataManager, TazDataIf tazDataHandler, int iteration, float iterationSampleRate) { + + this.resourceBundle = resourceBundle; + this.householdDataManager = householdDataManager; + this.iterationSampleRate = iterationSampleRate; + this.iteration = iteration; + this.tazDataHandler = tazDataHandler; + + lowVOTUpperBound = Float.parseFloat(resourceBundle.getString(PROPERTIES_LOWVOT_UPPERBOUND)); + numZones = Integer.parseInt(resourceBundle.getString(PROPERTIES_NUMZONES)); + folder = ResourceUtil.getProperty(resourceBundle, PROPERTIES_PROJECT_DIRECTORY) + "/" + + ResourceUtil.getProperty(resourceBundle, PROPERTIES_FOLDER); + timePeriodUpperBounds = ResourceUtil.getIntegerArray(resourceBundle, PROPERTIES_TIMEPERIOD_UPPERBOUNDS); + matrixNums = ResourceUtil.getArray(resourceBundle, PROPERTIES_TRIPMATRICES_NUMBERS); + matrixNames = ResourceUtil.getArray(resourceBundle, PROPERTIES_TRIPMATRICES_NAMES); + numTransitZones = Integer.parseInt(resourceBundle.getString(PROPERTIES_NUMTRANSITZONES)); + transitMatrixNums = ResourceUtil.getArray(resourceBundle, PROPERTIES_TRANSITMATRICES_NUMBERS); + transitMatrixNames = ResourceUtil.getArray(resourceBundle, PROPERTIES_TRANSITMATRICES_NAMES); + } + + public void writeMatrices() { + + logger.info("Writing CMAP trip matrices to EMME databanks"); + + try { + + //get person VOTs and user classes + getPersonVOTsAndUserClasses(); + + //read output files in order to get create trip matrices + readIndivTrips(); + readJointTrips(); + + //loop through time periods and create and write matrices + for(int i=0; i1) { + start_period = timePeriodUpperBounds[timePeriod-2]; + end_period = timePeriodUpperBounds[timePeriod-1]; + } + + //create output taz matrices for time period + matrices = new Matrix[matrixNames.length]; + for(int i=0; i start_period & stop_period[i] <= end_period) | (stop_period[i] > maxBound & timePeriod==1)) { + + //use parking taz instead for destination + if(parking_taz[i] > 0) { + dest_taz[i] = parking_taz[i]; + } + + //low or high income matrices + if(vots.get(Integer.valueOf(person_id[i])) <= lowVOTUpperBound) { + + if(trip_mode[i] == tripModeCode_DRIVEALONEFREE) { + float value = matrices[0].getValueAt(orig_taz[i], dest_taz[i]); + matrices[0].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_DRIVEALONEPAY) { + float value = matrices[1].getValueAt(orig_taz[i], dest_taz[i]); + matrices[1].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2FREE) { + float value = matrices[4].getValueAt(orig_taz[i], dest_taz[i]); + matrices[4].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov2occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED2PAY) { + float value = matrices[5].getValueAt(orig_taz[i], dest_taz[i]); + matrices[5].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov2occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED3FREE) { + float value = matrices[8].getValueAt(orig_taz[i], dest_taz[i]); + matrices[8].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov3occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED3PAY) { + float value = matrices[9].getValueAt(orig_taz[i], dest_taz[i]); + matrices[9].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov3occupancy); + } + + } else { + + if(trip_mode[i] == tripModeCode_DRIVEALONEFREE) { + float value = matrices[2].getValueAt(orig_taz[i], dest_taz[i]); + matrices[2].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_DRIVEALONEPAY) { + float value = matrices[3].getValueAt(orig_taz[i], dest_taz[i]); + matrices[3].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2FREE) { + float value = matrices[6].getValueAt(orig_taz[i], dest_taz[i]); + matrices[6].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov2occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED2PAY) { + float value = matrices[7].getValueAt(orig_taz[i], dest_taz[i]); + matrices[7].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov2occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED3FREE) { + float value = matrices[10].getValueAt(orig_taz[i], dest_taz[i]); + matrices[10].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov3occupancy); + } + + if(trip_mode[i] == tripModeCode_SHARED3PAY) { + float value = matrices[11].getValueAt(orig_taz[i], dest_taz[i]); + matrices[11].setValueAt(orig_taz[i], dest_taz[i], value + 1/hov3occupancy); + } + } + + //transit matrices + if(trip_mode[i] == tripModeCode_WALK_LOCAL) { + + if(purpose[i].toLowerCase().startsWith("work")) { + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[0].getValueAt(btap[i], atap[i]); + transitMatrices[0].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[1].getValueAt(btap[i], atap[i]); + transitMatrices[1].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[2].getValueAt(btap[i], atap[i]); + transitMatrices[2].setValueAt(btap[i], atap[i], value + 1); + } + + } else { + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[0].getValueAt(btap[i], atap[i]); + transitMatrices[0].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[1].getValueAt(btap[i], atap[i]); + transitMatrices[1].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[2].getValueAt(btap[i], atap[i]); + transitMatrices[2].setValueAt(btap[i], atap[i], value + 1); + } + + } + + } + + if(trip_mode[i] == tripModeCode_WALK_PREMIUM) { + + if(purpose[i].toLowerCase().startsWith("work")) { + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_walk.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + 1); + } + + } else { + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_walk.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + 1); + } + + } + } + + if(trip_mode[i] == tripModeCode_DRIVE_PREMIUM | trip_mode[i] == tripModeCode_DRIVE_LOCAL) { + + if(purpose[i].startsWith("work")) { + + if(user_class_work_pnr.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_pnr.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_work_pnr.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + 1); + } + + } else { + + if(user_class_non_work_pnr.get(Integer.valueOf(person_id[i])) == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_pnr.get(Integer.valueOf(person_id[i])) == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + 1); + } + + if(user_class_non_work_pnr.get(Integer.valueOf(person_id[i])) == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + 1); + } + + } + } + + } + } + + //get jointTrips fields + hh_id = indivTrips.getColumnAsInt("hh_id"); + orig_taz = jointTrips.getColumnAsInt("orig_taz"); + dest_taz = jointTrips.getColumnAsInt("dest_taz"); + parking_taz = jointTrips.getColumnAsInt("parking_taz"); + stop_period = jointTrips.getColumnAsInt("stop_period"); + trip_mode = jointTrips.getColumnAsInt("trip_mode"); + inbound = jointTrips.getColumnAsInt("inbound"); + int[] num_participants = jointTrips.getColumnAsInt("num_participants"); //for transit trips + + btap = jointTrips.getColumnAsInt("board_tap"); + atap = jointTrips.getColumnAsInt("alight_tap"); + purpose = indivTrips.getColumnAsString("dest_purpose"); + + for(int i=0; i start_period & stop_period[i] <= end_period) | (stop_period[i] > maxBound & timePeriod==1)) { + + //get hh level attributes + float hh_vot = vots.get(oldestPersonId.get(Integer.valueOf(hh_id[i]))); + int hh_user_class_non_work_walk = user_class_non_work_walk.get(oldestPersonId.get(Integer.valueOf(hh_id[i]))); + int hh_user_class_non_work_pnr = user_class_non_work_pnr.get(oldestPersonId.get(Integer.valueOf(hh_id[i]))); + int hh_user_class_non_work_knr = user_class_non_work_knr.get(oldestPersonId.get(Integer.valueOf(hh_id[i]))); + + //use parking taz instead for destination + if(parking_taz[i] > 0) { + dest_taz[i] = parking_taz[i]; + } + + //low or high income matrices + if(hh_vot <= lowVOTUpperBound) { + + if(trip_mode[i] == tripModeCode_DRIVEALONEFREE) { + float value = matrices[0].getValueAt(orig_taz[i], dest_taz[i]); + matrices[0].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_DRIVEALONEPAY) { + float value = matrices[1].getValueAt(orig_taz[i], dest_taz[i]); + matrices[1].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2FREE) { + float value = matrices[4].getValueAt(orig_taz[i], dest_taz[i]); + matrices[4].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2PAY) { + float value = matrices[5].getValueAt(orig_taz[i], dest_taz[i]); + matrices[5].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED3FREE) { + float value = matrices[8].getValueAt(orig_taz[i], dest_taz[i]); + matrices[8].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED3PAY) { + float value = matrices[9].getValueAt(orig_taz[i], dest_taz[i]); + matrices[9].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + } else { + + if(trip_mode[i] == tripModeCode_DRIVEALONEFREE) { + float value = matrices[2].getValueAt(orig_taz[i], dest_taz[i]); + matrices[2].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_DRIVEALONEPAY) { + float value = matrices[3].getValueAt(orig_taz[i], dest_taz[i]); + matrices[3].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2FREE) { + float value = matrices[6].getValueAt(orig_taz[i], dest_taz[i]); + matrices[6].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED2PAY) { + float value = matrices[7].getValueAt(orig_taz[i], dest_taz[i]); + matrices[7].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED3FREE) { + float value = matrices[10].getValueAt(orig_taz[i], dest_taz[i]); + matrices[10].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + + if(trip_mode[i] == tripModeCode_SHARED3PAY) { + float value = matrices[11].getValueAt(orig_taz[i], dest_taz[i]); + matrices[11].setValueAt(orig_taz[i], dest_taz[i], value + 1); + } + } + + //transit matrices + if(trip_mode[i] == tripModeCode_WALK_LOCAL) { + + if(hh_user_class_non_work_walk == 1) { + float value = transitMatrices[0].getValueAt(btap[i], atap[i]); + transitMatrices[0].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_walk == 2) { + float value = transitMatrices[1].getValueAt(btap[i], atap[i]); + transitMatrices[1].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_walk == 3) { + float value = transitMatrices[2].getValueAt(btap[i], atap[i]); + transitMatrices[2].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + } + + if(trip_mode[i] == tripModeCode_WALK_PREMIUM ) { + + if(hh_user_class_non_work_walk == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_walk == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_walk == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + } + + if(trip_mode[i] == tripModeCode_DRIVE_PREMIUM | trip_mode[i] == tripModeCode_DRIVE_LOCAL) { + + if(hh_user_class_non_work_pnr == 1) { + float value = transitMatrices[3].getValueAt(btap[i], atap[i]); + transitMatrices[3].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_pnr == 2) { + float value = transitMatrices[4].getValueAt(btap[i], atap[i]); + transitMatrices[4].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + + if(hh_user_class_non_work_pnr == 3) { + float value = transitMatrices[5].getValueAt(btap[i], atap[i]); + transitMatrices[5].setValueAt(btap[i], atap[i], value + num_participants[i]); + } + } + + } + } + + //scale matrices by sample rate + for(int i=0; i(); + oldestPersonId = new HashMap(); + + //create user class hash maps + user_class_work_walk = new HashMap(); + user_class_work_pnr = new HashMap(); + user_class_work_knr = new HashMap(); + user_class_non_work_walk = new HashMap(); + user_class_non_work_pnr = new HashMap(); + user_class_non_work_knr = new HashMap(); + + //loop through households and add person measures to hash maps + int numhhs = householdDataManager.getNumHouseholds(); + for (int i=0; i 0 ) { + String base = originalFileName.substring( 0, lastDot ); + String ext = originalFileName.substring( lastDot ); + returnString = String.format( "%s_%d%s", base, iteration, ext ); + } + else { + returnString = String.format( "%s_%d.csv", originalFileName, iteration ); + } + return returnString; + } + +} diff --git a/src/java/com/pb/cmap/tourBased/CmapTripModeChoiceDMU.java b/src/java/com/pb/cmap/tourBased/CmapTripModeChoiceDMU.java new file mode 100644 index 0000000..bd4f8ef --- /dev/null +++ b/src/java/com/pb/cmap/tourBased/CmapTripModeChoiceDMU.java @@ -0,0 +1,393 @@ +package com.pb.cmap.tourBased; + +import java.util.HashMap; + +import com.pb.cmap.tourBased.CmapModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TripModeChoiceDMU; + + +public class CmapTripModeChoiceDMU extends TripModeChoiceDMU { + + CmapModelStructure modelStructure; + int[] zoneTableRow; + int[] areaType; + float[] prkCost; + + int[] tazForMaz; + + TazDataIf tazDataManager; + + public CmapTripModeChoiceDMU(TazDataIf tazDataManager, CmapModelStructure modelStructure){ + super(tazDataManager, modelStructure ); + this.modelStructure = modelStructure; + setup( tazDataManager ); + setupMethodIndexMap(); + } + + + private void setup( TazDataIf tazDataManager ) { + + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + + tazForMaz = tazDataManager.getTazsForMazs(); + + this.tazDataManager = tazDataManager; + + } + + + // fixed Structure value -- need to update to use ModelStructure + // TODO update to make general using ModelStructure and remove zdm + public int getRuralDestination() { + + //TODO: Kim review with Jim. + //int at = tazDataManager.getZonalAreaType( tour.getTourDestTaz() ); + int at = areaType[tour.getTourDestTaz() - 1]; + + if ( at == 7 ) // Structure.AreaType.RURAL.ordinal() ) + return 1; + else + return 0; + } + + public int getHhSize() { + return hh.getHhSize(); + } + + public int getAutos() { + return hh.getAutoOwnershipModelResult(); + } + + public int getDrivers() { + return hh.getDrivers(); + } + + public int getAge() { + return person.getAge(); + } + + public int getIncome() { + return hh.getIncomeSegment(); + } + + + public int getAgeUnder40() { + if ( person.getAge() < 40 ) + return 1; + else + return 0; + } + + public int getAge40to59() { + if ( person.getAge() >= 40 && person.getAge() < 60 ) + return 1; + else + return 0; + } + + public int getAge60to79() { + if ( person.getAge() >= 60 && person.getAge() < 79 ) + return 1; + else + return 0; + } + + public int getAge60plus() { + if ( person.getAge() >= 60 ) + return 1; + else + return 0; + } + + public int getPersonIsWorker() { + return person.getPersonIsWorker(); + } + + public int getPersonIsNonWorkingAdult() { + if ( person.getPersonIsNonWorkingAdultUnder65() == 1 ) + return 1; + else + return 0; + } + + public int getPersonIsMale() { + if ( person.getPersonIsMale() == 1 ) + return 1; + else + return 0; + } + + + public int getPreDrivingChildInHh() { + if ( hh.getNumChildrenUnder16() > 0 ) + return 1; + else + return 0; + } + + public int getNumFemalesInHh() { + int count = 0; + PersonIf[] persons = hh.getPersons(); + for (int i=1; i < persons.length; i++){ + if ( persons[i].getPersonIsFemale() == 1 ) + count++; + } + return count; + } + + public int getFreeParking() { + return person.getFreeParkingAvailableResult(); + } + + + + public int getHomemaker() { + return person.getHomemaker(); + } + + public int getWorkers() { + return hh.getWorkers(); + } + + public int getOutboundStops() { + return tour.getNumOutboundStops(); + } + + public int getInboundStops() { + return tour.getNumInboundStops(); + } + + public int getSize() { + return hh.getSize(); + } + + public int getGender() { + return person.getGender(); + } + + public int getChildunder16() { + return hh.getChildunder16(); + } + + public int getChild16plus() { + return hh.getChild16plus(); + } + + + public int getTourPurposeEscort() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getEscortPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPurposeShopping() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getShoppingPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPurposeEatOut() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getEatOutPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPurposeSocial() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getSocialPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPurposeOthDiscr() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getOthDiscrPurposeName() ) ) + return 1; + else + return 0; + } + + public int getInbound() { + return stop.isInboundStop() ? 1 : 0; + } + + public int getTodOut() { + return modelStructure.getTod( stop.getStopPeriod() ); + } + + public int getTourTodOut() { + return modelStructure.getTod(stop.getTourDepartPeriod() ); + } + + public int getTourTodIn() { + return modelStructure.getTod( tour.getTourArrivePeriod() ); + } + + + public int getOmazOtaz() { + return tazForMaz[dmuIndex.getOriginZone()-1]; + } + + public int getDmazDtaz() { + return tazForMaz[dmuIndex.getDestZone()-1]; + } + + + + public double getOMazDMazDistance() { + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), dmuIndex.getDestZone()); + } + + private void setupMethodIndexMap() { + methodIndexMap = new HashMap(); + + methodIndexMap.put( "getTodOut", 0 ); + methodIndexMap.put( "getTourTodIn", 1 ); + methodIndexMap.put( "getZonalShortWalkAccessOrig", 2 ); + methodIndexMap.put( "getZonalShortWalkAccessDest", 3 ); + methodIndexMap.put( "getZonalLongWalkAccessOrig", 4 ); + methodIndexMap.put( "getZonalLongWalkAccessDest", 5 ); + methodIndexMap.put( "getRuralDestination", 6 ); + methodIndexMap.put( "getHhSize", 7 ); + methodIndexMap.put( "getAutos", 8 ); + methodIndexMap.put( "getDrivers", 9 ); + methodIndexMap.put( "getAge", 10 ); + methodIndexMap.put( "getIncome", 11 ); + methodIndexMap.put( "getAgeUnder40", 12 ); + methodIndexMap.put( "getAge40to59", 13 ); + methodIndexMap.put( "getAge60to79", 14 ); + methodIndexMap.put( "getAge60plus", 15 ); + methodIndexMap.put( "getPersonIsWorker", 16 ); + methodIndexMap.put( "getPersonIsNonWorkingAdult", 17 ); + methodIndexMap.put( "getPersonIsMale", 18 ); + methodIndexMap.put( "getPreDrivingChildInHh", 19 ); + methodIndexMap.put( "getNumFemalesInHh", 20 ); + methodIndexMap.put( "getFreeParking", 23 ); + methodIndexMap.put( "getHomemaker", 24 ); + methodIndexMap.put( "getWorkers", 25 ); + methodIndexMap.put( "getOutboundStops", 26 ); + methodIndexMap.put( "getInboundStops", 27 ); + methodIndexMap.put( "getSize", 28 ); + methodIndexMap.put( "getGender", 29 ); + methodIndexMap.put( "getChildunder16", 30 ); + methodIndexMap.put( "getChild16plus", 31 ); + methodIndexMap.put( "getTourCategoryJoint", 32 ); + methodIndexMap.put( "getTourPurposeEscort", 33 ); + methodIndexMap.put( "getTourPurposeShopping", 34 ); + methodIndexMap.put( "getTourPurposeEatOut", 35 ); + methodIndexMap.put( "getTourPurposeSocial", 36 ); + methodIndexMap.put( "getTourPurposeOthDiscr", 37 ); + methodIndexMap.put( "getNumberOfParticipantsInJointTour", 38 ); + methodIndexMap.put( "getWorkTourModeIsSOV", 39 ); + methodIndexMap.put( "getWorkTourModeIsBike", 40 ); + methodIndexMap.put( "getTourMode", 41 ); + methodIndexMap.put( "getSubtourType", 42 ); + methodIndexMap.put( "getOrigType", 43 ); + methodIndexMap.put( "getDestType", 44 ); + methodIndexMap.put( "getOrigParkRate", 45 ); + methodIndexMap.put( "getIntStopParkRate", 46 ); + methodIndexMap.put( "getPrimDestParkRate", 47 ); + methodIndexMap.put( "getInbound", 48 ); + + methodIndexMap.put( "getOmazOtaz", 60 ); + methodIndexMap.put( "getDmazDtaz", 61 ); + + methodIndexMap.put( "getGenCostWT", 70 ); + methodIndexMap.put( "getGenCostDL", 71 ); + methodIndexMap.put( "getGenCostDP", 72 ); + methodIndexMap.put( "getOtapWT", 73 ); + methodIndexMap.put( "getDtapWT", 74 ); + methodIndexMap.put( "getOtapDL", 75 ); + methodIndexMap.put( "getDtapDL", 76 ); + + methodIndexMap.put( "getOtapDP", 77 ); + methodIndexMap.put( "getDtapDP", 78 ); + + methodIndexMap.put( "getOMazDMazDistance", 88 ); + } + + + + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getTodOut(); + case 1: return getTourTodIn(); + case 2: return getZonalShortWalkAccessOrig(); + case 3: return getZonalShortWalkAccessDest(); + case 4: return getZonalLongWalkAccessOrig(); + case 5: return getZonalLongWalkAccessDest(); + case 6: return getRuralDestination(); + case 7: return getHhSize(); + case 8: return getAutos(); + case 9: return getDrivers(); + case 10: return getAge(); + case 11: return getIncome(); + case 12: return getAgeUnder40(); + case 13: return getAge40to59(); + case 14: return getAge60to79(); + case 15: return getAge60plus(); + case 16: return getPersonIsWorker(); + case 17: return getPersonIsNonWorkingAdult(); + case 18: return getPersonIsMale(); + case 19: return getPreDrivingChildInHh(); + case 20: return getNumFemalesInHh(); + case 23: return getFreeParking(); + case 24: return getHomemaker(); + case 25: return getWorkers(); + case 26: return getOutboundStops(); + case 27: return getInboundStops(); + case 28: return getSize(); + case 29: return getGender(); + case 30: return getChildunder16(); + case 31: return getChild16plus(); + case 32: return getTourCategoryJoint(); + case 33: return getTourPurposeEscort(); + case 34: return getTourPurposeShopping(); + case 35: return getTourPurposeEatOut(); + case 36: return getTourPurposeSocial(); + case 37: return getTourPurposeOthDiscr(); + case 38: return getNumberOfParticipantsInJointTour(); + case 39: return getWorkTourModeIsSOV(); + case 40: return getWorkTourModeIsBike(); + case 41: return getTourMode(); + case 42: return getSubtourType(); + case 43: return getOrigType(); + case 44: return getDestType(); + case 45: return getOrigParkRate(); + case 46: return getIntStopParkRate(); + case 47: return getPrimDestParkRate(); + case 48: return getInbound(); + + case 60: return getOmazOtaz(); + case 61: return getDmazDtaz(); + + case 70: return getGenCostWT(); + case 71: return getGenCostDL(); + case 72: return getGenCostDP(); + case 73: return getOtapWT(); + case 74: return getDtapWT(); + case 75: return getOtapDL(); + case 76: return getDtapDL(); + case 77: return getOtapDP(); + case 78: return getDtapDP(); + + case 88: return getOMazDMazDistance(); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + + } + + } + +} \ No newline at end of file diff --git a/src/java/com/pb/cmap/tvpb/MazTapTazData.java b/src/java/com/pb/cmap/tvpb/MazTapTazData.java new file mode 100644 index 0000000..1c59cd1 --- /dev/null +++ b/src/java/com/pb/cmap/tvpb/MazTapTazData.java @@ -0,0 +1,754 @@ +package com.pb.cmap.tvpb; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.TreeSet; + +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.util.ResourceUtil; +import com.pb.common.matrix.Matrix; + +import org.apache.log4j.Logger; + +public class MazTapTazData implements Serializable { + + private static Logger logger = Logger.getLogger(TransitVirtualPathBuilder.class); + private transient Logger tvpbLogger = Logger.getLogger("tvpbLog"); + + private TableDataSet maz2tapTable; + private TableDataSet tapTable; + private TableDataSet tapLinesTable; + private TableDataSet mazTable; + + private HashMap> omazWalkTapsDist; + private HashMap> dmazWalkTapsDist; + private HashMap> mazPnrTapsDist; + private HashMap> mazMazDist; + + private HashMap taptaz; + private HashMap taplines; + private HashMap> taztaps; + private HashMap tapCanPnr; + private HashMap maztaz; + private HashMap mazclosestTap; + private HashMap mazclosestPnrTap; + private HashMap maztransit; + + private int[] uniqTazs; + private int[] mazs; + private int[] tazs; + private String tapid; + private Matrix tazDistanceMatrix; + private Matrix mazDistanceMatrix; //very big but not currently used + + private HashMap omazWalkTapsDistSorted = new HashMap(); + private HashMap dmazWalkTapsDistSorted = new HashMap(); + private HashMap mazPnrTapsDistSorted = new HashMap(); + + private int maxTransitStopWalkDist = 5280; + + public MazTapTazData(HashMap propertyMap) throws IOException { + + //---------------------------------------------- + //read maz table + //---------------------------------------------- + CSVFileReader csvReader = new CSVFileReader(); + String mazTableFileName = propertyMap.get("tvpb.mazfile"); + try { + mazTable = csvReader.readFile( new File(mazTableFileName)); + } catch (IOException e) { + throw new IOException(); + } + + //get maz table field names + String maz = propertyMap.get("tvpb.mazfile.maz"); + String taz = propertyMap.get("tvpb.mazfile.taz"); + + mazs = mazTable.getColumnAsInt(maz); + tazs = mazTable.getColumnAsInt(taz); + + //create unique set of tazs + TreeSet tempTazs = new TreeSet(); + for (int aTaz : tazs) { + tempTazs.add(aTaz); + } + uniqTazs = new int[tempTazs.size()]; + int z=0; + for(Integer aTaz : tempTazs) { + uniqTazs[z] = aTaz; + z++; + } + + //create lookup + maztaz = new HashMap(); + for(int i=0; i>(); + taptaz = new HashMap(); + tapCanPnr = new HashMap(); + for(int i=0; i updatedTaz = taztaps.get(tazIds[i]); + updatedTaz.add(tapIds[i]); + taztaps.put(tazIds[i], updatedTaz); + } else { + ArrayList initTap = new ArrayList(); + initTap.add(tapIds[i]); + taztaps.put(tazIds[i], initTap); + } + } + + //---------------------------------------------- + //read tap lines table + //---------------------------------------------- + String tapLinesTableFileName = propertyMap.get("tvpb.tapLines"); + try { + tapLinesTable = csvReader.readFile( new File(tapLinesTableFileName)); + } catch (IOException e) { + throw new IOException(); + } + + //get tap lines table field names + String tapLinesTapId = propertyMap.get("tvpb.tapLines.tapid"); + String lines = propertyMap.get( "tvpb.tapLines.lines"); + int[] tapLinesTapIds = tapLinesTable.getColumnAsInt(tapLinesTapId); + String[] linesForTap = tapLinesTable.getColumnAsString(lines); + + //create lookups + taplines = new HashMap(); + for(int i=0; i>(); + dmazWalkTapsDist = new HashMap>(); + mazMazDist = new HashMap>(); + + //create dictionaries of taps by origin and destination + for(int i=0; i updatedTapsDist = omazWalkTapsDist.get(origins[i]); + updatedTapsDist.put(dests[i], (float)distances[i]); + omazWalkTapsDist.put(origins[i], updatedTapsDist); + + } else { + + HashMap initTapDist = new HashMap(); + initTapDist.put(dests[i], (float)distances[i]); + omazWalkTapsDist.put(origins[i], initTapDist); + } + + } + + //if origin is TAP and dest is MAZ + if(taptaz.containsKey(origins[i]) & maztaz.containsKey(dests[i])) { + + //store distances + if(dmazWalkTapsDist.containsKey(dests[i])) { + + HashMap updatedTapsDist = dmazWalkTapsDist.get(dests[i]); + updatedTapsDist.put(origins[i], (float)distances[i]); + dmazWalkTapsDist.put(dests[i], updatedTapsDist); + + } else { + + HashMap initTapDist = new HashMap(); + initTapDist.put(origins[i], (float)distances[i]); + dmazWalkTapsDist.put(dests[i], initTapDist); + } + + } + + //if origin is MAZ and dest is MAZ + if(maztaz.containsKey(origins[i]) & maztaz.containsKey(dests[i])) { + + if(mazMazDist.containsKey(origins[i])) { + + HashMap updatedMazsDist = mazMazDist.get(origins[i]); + updatedMazsDist.put(dests[i], (float)distances[i]); + mazMazDist.put(origins[i], updatedMazsDist); + + } else { + + HashMap initMazDist = new HashMap(); + initMazDist.put(dests[i], (float)distances[i]); + mazMazDist.put(origins[i], initMazDist); + } + + } + } + + //---------------------------------------------- + //trim the near tap set by origin/destination by only including the nearest tap + //when more than one tap serves the same line. + //---------------------------------------------- + int omazToOTaps = 0; + int trimmedOTaps = 0; + for(Integer omaz : omazWalkTapsDist.keySet()) { + + //get taps and distance and lines + HashMap tapsForMazDist = omazWalkTapsDist.get(omaz); + ArrayList maz2TapData = new ArrayList(); + + for (Integer tapId : tapsForMazDist.keySet()) { + + Maz2Tap m2t = new Maz2Tap(); + m2t.tap = tapId; + m2t.dist = tapsForMazDist.get(tapId); + if(taplines.containsKey(tapId)) { //else drop tap from list + m2t.lines = taplines.get(tapId).split(" "); + } + maz2TapData.add(m2t); + + } + + //sort by distance and check for new lines + Collections.sort(maz2TapData); + HashMap linesServed = new HashMap(); + for (Maz2Tap m2t : maz2TapData) { + + //skip if no lines served + if(m2t.lines != null) { + + for (int i=0; i tapsForMazDist = dmazWalkTapsDist.get(dmaz); + ArrayList maz2TapData = new ArrayList(); + + for (Integer tapId : tapsForMazDist.keySet()) { + + Maz2Tap m2t = new Maz2Tap(); + m2t.tap = tapId; + m2t.dist = tapsForMazDist.get(tapId); + if(taplines.containsKey(tapId)) { //else drop tap from list + m2t.lines = taplines.get(tapId).split(" "); + } + maz2TapData.add(m2t); + + } + + //sort by distance and check for new lines + Collections.sort(maz2TapData); + HashMap linesServed = new HashMap(); + for (Maz2Tap m2t : maz2TapData) { + + //skip if no lines served + if(m2t.lines != null) { + + for (int i=0; i tazNumbers = new ArrayList(); + for (Integer i : tazNums) { + tazNumbers.add(i); + } + + //for each maz, get its taz, then the closest pnr tap and all taps within threshold + mazclosestPnrTap = new HashMap(); + mazPnrTapsDist = new HashMap>(); + mazclosestTap = new HashMap(); + for(Integer maz : maztaz.keySet()) { + + //get maz's taz + int taz = maztaz.get(maz); + + //get the distance to each taz from the maz's taz + float[] distToTazs = dist[tazNumbers.indexOf(taz)]; + + double minDist = 999*5280; + int minDistTap = 0; + double minDistPnr = 999*5280; + int minDistPnrTap = 0; + for (int i=0; i tapsForTaz = taztaps.get(tazNums[i]); + if(tapsForTaz!=null) { + + //skip unavailable tazs + if(distToTazs[i] <= maxPnrDist) { + + //@todo - for now take arbitrary tap in the taz since each tap has the same taz distance + if(distToTazs[i] < minDist) { + minDistTap = tapsForTaz.get(0); //index 0 since ArrayList + minDist = distToTazs[i]; + } + + //reduce set of taps to those that can pnr + ArrayList tapsForTazPnr = new ArrayList(); + HashMap tapsForTazPnrDist = new HashMap(); + for (Integer tapId : tapsForTaz) { + if(tapCanPnr.get(tapId)==1) { + tapsForTazPnr.add(tapId); + tapsForTazPnrDist.put(tapId, distToTazs[i]); + } + } + + //process pnr taps if there are some + if(tapsForTazPnr.size()>0) { + + //put all taps in the pnr tap set for the maz + if(mazPnrTapsDist.containsKey(maz)) { + + HashMap updatedTapsDist = mazPnrTapsDist.get(maz); + updatedTapsDist.putAll(tapsForTazPnrDist); + mazPnrTapsDist.put(maz, updatedTapsDist); + + } else { + + HashMap initTapDist = new HashMap(); + initTapDist.putAll(tapsForTazPnrDist); + mazPnrTapsDist.put(maz, initTapDist); + + } + + //@todo - for now take arbitrary pnr tap in the taz since each tap has the same taz distance + if(distToTazs[i] < minDistPnr) { + minDistPnrTap = tapsForTazPnr.get(0); //index 0 since ArrayList + minDistPnr = distToTazs[i]; + } + + } + + } + + } + + } + + //store closest tap and pnr tap by maz + mazclosestTap.put(maz, minDistTap); + mazclosestPnrTap.put(maz, minDistPnrTap); + } + + //---------------------------------------------- + //trim the near tap set by origin/destination by only including the nearest tap + //when more than one tap serves the same line. + //---------------------------------------------- + int mazToPnrTaps = 0; + int trimmedPnrTaps = 0; + for(Integer maz : mazPnrTapsDist.keySet()) { + + //get taps and distance and lines + HashMap tapsForMazDist = mazPnrTapsDist.get(maz); + ArrayList maz2TapData = new ArrayList(); + + for (Integer tapId : mazPnrTapsDist.get(maz).keySet()) { + + Maz2Tap m2t = new Maz2Tap(); + m2t.tap = tapId; + m2t.dist = tapsForMazDist.get(tapId); + if(taplines.containsKey(tapId)) { //else drop tap from list + m2t.lines = taplines.get(tapId).split(" "); + } + maz2TapData.add(m2t); + + } + + //sort by distance and check for new lines + Collections.sort(maz2TapData); + HashMap linesServed = new HashMap(); + for (Maz2Tap m2t : maz2TapData) { + + //skip if no lines served + if(m2t.lines != null) { + + for (int i=0; i(); + + for(int i=0; i> tapsListDist, HashMap tapsDistSorted) { + + //loop by maz + for(Integer maz : tapsListDist.keySet()) { + + //create maz2taps to sort + ArrayList mt = new ArrayList(); + HashMap tapDists = tapsListDist.get(maz); + + if(tapDists.size()>0) { + + //add data and sort + for(Integer tap : tapDists.keySet()) { + Maz2Tap x = new Maz2Tap(); + x.tap = tap; + x.dist = tapDists.get(tap); + mt.add(x); + } + Collections.sort(mt); + + //convert to TapDist simple object + TapDist[] td = new TapDist[mt.size()]; + for(int i=0; i tapsDistSorted, int maz, double maxDist) { + + //get tap distances + TapDist[] tapsDist = tapsDistSorted.get(maz); + + //return array + if(tapsDist != null) { + + //filter on distance + int keepCount = 0 ; + while(tapsDist[keepCount].dist <= maxDist) { + keepCount++; + if(keepCount == tapsDist.length) { + break; + } + } + + TapDist[] ret = new TapDist[keepCount]; + for(int i=0; i(); + + methodIndexMap.put( "getAge", 0 ); + methodIndexMap.put( "getUserClass", 1 ); + methodIndexMap.put( "getCars", 2 ); + methodIndexMap.put( "getTod", 3 ); + methodIndexMap.put( "getInbound", 4 ); + methodIndexMap.put( "getIsWalkTapPair", 5 ); + methodIndexMap.put( "getIsPnrTapPair", 6 ); + methodIndexMap.put( "getIsKnrTapPair", 7 ); + methodIndexMap.put( "getMaz2TapDistance", 8 ); + methodIndexMap.put( "getClosestPnrTapTaz", 9 ); + methodIndexMap.put( "getClosestTapTaz", 10 ); + methodIndexMap.put( "getHhincome", 11 ); + methodIndexMap.put( "getEduc", 12 ); + methodIndexMap.put( "getGender", 13 ); + methodIndexMap.put( "getPurpose", 14 ); + + methodIndexMap.put( "getStop_type_btap", 20); + methodIndexMap.put( "getReltime_if_btap", 21); + methodIndexMap.put( "getF_pnr_sp_btap", 22); + methodIndexMap.put( "getIf_pnr_sp_btap", 23); + methodIndexMap.put( "getDpark_cost_btap", 24); + methodIndexMap.put( "getLot_time_btap", 25); + methodIndexMap.put( "getKnr_convf_btap", 26); + methodIndexMap.put( "getCrime_rate_btap", 27); + methodIndexMap.put( "getRetail_den_btap", 28); + methodIndexMap.put( "getFare_1brd_btap", 29); + + methodIndexMap.put( "getStop_type_atap", 40); + methodIndexMap.put( "getReltime_if_atap", 41); + methodIndexMap.put( "getF_pnr_sp_atap", 42); + methodIndexMap.put( "getIf_pnr_sp_atap", 43); + methodIndexMap.put( "getDpark_cost_atap", 44); + methodIndexMap.put( "getLot_time_atap", 45); + methodIndexMap.put( "getKnr_convf_atap", 46); + methodIndexMap.put( "getCrime_rate_atap", 47); + methodIndexMap.put( "getRetail_den_atap", 48); + methodIndexMap.put( "getFare_1brd_atap", 49); + + methodIndexMap.put( "getWalkTimeWeight", 50); + methodIndexMap.put( "getWalkSpeed", 51); + methodIndexMap.put( "getMaxWalk", 52); + methodIndexMap.put( "getValueOfTime", 53); + + methodIndexMap.put( "getUserClassWorkWalk", 60); + methodIndexMap.put( "getUserClassWorkPnr", 61); + methodIndexMap.put( "getUserClassWorkKnr", 62); + + methodIndexMap.put( "getUserClassNonWorkWalk", 63); + methodIndexMap.put( "getUserClassNonWorkPnr", 64); + methodIndexMap.put( "getUserClassNonWorkKnr", 65); + + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + + switch ( variableIndex ){ + case 0: return getAge(); + case 1: return getUserClass(); + case 2: return getCars(); + case 3: return getTod(); + case 4: return getInbound(); + case 5: return getIsWalkTapPair(); + case 6: return getIsPnrTapPair(); + case 7: return getIsKnrTapPair(); + case 8: return getMaz2TapDistance(); + case 9: return getClosestPnrTapTaz(); + case 10: return getClosestTapTaz(); + case 11: return getHhincome(); + case 12: return getEduc(); + case 13: return getGender(); + case 14: return getPurpose(); + + case 20: return getStop_type_btap(); + case 21: return getReltime_if_btap(); + case 22: return getF_pnr_sp_btap(); + case 23: return getIf_pnr_sp_btap(); + case 24: return getDpark_cost_btap(); + case 25: return getLot_time_btap(); + case 26: return getKnr_convf_btap(); + case 27: return getCrime_rate_btap(); + case 28: return getRetail_den_btap(); + case 29: return getFare_1brd_btap(); + + case 40: return getStop_type_atap(); + case 41: return getReltime_if_atap(); + case 42: return getF_pnr_sp_atap(); + case 43: return getIf_pnr_sp_atap(); + case 44: return getDpark_cost_atap(); + case 45: return getLot_time_atap(); + case 46: return getKnr_convf_atap(); + case 47: return getCrime_rate_atap(); + case 48: return getRetail_den_atap(); + case 49: return getFare_1brd_atap(); + + case 50: return getWalkTimeWeight(); + case 51: return getWalkSpeed(); + case 52: return getMaxWalk(); + case 53: return getValueOfTime(); + + case 60: return getUserClassByType("user_class_work_walk"); + case 61: return getUserClassByType("user_class_work_pnr"); + case 62: return getUserClassByType("user_class_work_knr"); + case 63: return getUserClassByType("user_class_non_work_walk"); + case 64: return getUserClassByType("user_class_non_work_pnr"); + case 65: return getUserClassByType("user_class_non_work_knr"); + + default: + logger.error("method number = "+variableIndex+" not found"); + throw new RuntimeException("method number = "+variableIndex+" not found"); + } + } + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + + +} diff --git a/src/java/com/pb/cmap/tvpb/TapPair.java b/src/java/com/pb/cmap/tvpb/TapPair.java new file mode 100644 index 0000000..b5cef32 --- /dev/null +++ b/src/java/com/pb/cmap/tvpb/TapPair.java @@ -0,0 +1,84 @@ +package com.pb.cmap.tvpb; + +public class TapPair implements Comparable{ + + public int otap; + public int dtap; + public int otaptaz; + public int dtaptaz; + public boolean isWalkTapPair = false; + public boolean isPnrTapPair = false; + public boolean isKnrTapPair = false; + public int NA_VALUE = 0; //0 since all valid paths have a positive generalized cost + + public double[] maz2tapUtils; + public double[] otapUtils; + public double[] tap2tapUtils; + public double[] dtapUtils; + public double[] tap2mazUtils; + + public TapPair(int otap, int dtap, boolean isWalkTapPair, boolean isPnrTapPair, boolean isKnrTapPair, int alts) { + this.otap = otap; + this.dtap = dtap; + this.isWalkTapPair = isWalkTapPair; + this.isPnrTapPair = isPnrTapPair; + this.isKnrTapPair = isKnrTapPair; + + maz2tapUtils = new double[alts]; + otapUtils = new double[alts]; + tap2tapUtils = new double[alts]; + dtapUtils = new double[alts]; + tap2mazUtils = new double[alts]; + + } + + public double[] getTotalUtils() { + + double[] totalUtils = new double[maz2tapUtils.length]; + for(int i=0; i propertyMap; + + private static final String TVPB_UEC = "tvpb.uec"; + private static final int DATA_SHEET = 0; + private static final int MAZ2TAP_SHEET = 1; + private static final int OTAP_SHEET = 2; + private static final int TAP2TAP_SHEET = 3; + private static final int DTAP_SHEET = 4; + private static final int TAP2MAZ_SHEET = 5; + private static final int TAZDISTANCE_SHEET = 6; + private static final int forkJoinMinCalcSize = 10; + + private ThreadLocal threadSafeUECs; + private UtilityExpressionCalculator[] uecs; + private Trip[] trips; + private MazTapTazData mttData; + private MatrixDataServerIf ms; + private String uecFileName; + private boolean runThreaded; + private double maxWalkDist; + private double maxTotalWalkDist; + private double maxPnrDist; + private int alts; + private int[] nAlts = new int[alts+1]; + private boolean trace; + + private int maxWalkPaths; + private int maxKNRPaths; + private int maxPNRPaths; + + private int NA_VALUE = 0; //since using gen cost + + public TransitVirtualPathBuilder(HashMap propertyMap) { + this.propertyMap = propertyMap; + } + + public static void main(String[] args) { + + // get the properties file + logger.info("Running Transit Virtual Path Builder"); + ResourceBundle resourceBundle = ResourceUtil.getResourceBundle("cmap"); + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + TransitVirtualPathBuilder tvpb = new TransitVirtualPathBuilder(propertyMap); + + //setup and run + tvpb.setupTVPB(); + tvpb.setupModels(); + tvpb.readTripData(); + tvpb.createMazTapTazData(); + tvpb.calculatePaths(); + tvpb.writeOutputData(); + + //all done + logger.info("Transit Virtual Path Builder Done"); + } + + public void setupTVPB() { + + //setup + connectToMatrixServer(); + getProperties(); + } + + public void getProperties() { + + // get properties + String projectDirectory = propertyMap.get("Project.Directory"); + String uecFile = propertyMap.get(TVPB_UEC); + uecFileName = projectDirectory + uecFile; + runThreaded = Boolean.parseBoolean(propertyMap.get("tvpb.runthreaded")); + maxWalkDist = Double.parseDouble(propertyMap.get("tvpb.maxwalkdist")); + maxTotalWalkDist = Double.parseDouble(propertyMap.get("tvpb.maxtotalwalkdist")); + maxPnrDist = Double.parseDouble(propertyMap.get("tvpb.maxpnrdist")); + alts = Integer.parseInt(propertyMap.get("tvpb.alts")); + trace = Boolean.parseBoolean(propertyMap.get("tvpb.trace")); + + //path set trimming settings + maxWalkPaths = Integer.parseInt(propertyMap.get("tvpb.maxpaths.walk")); + maxKNRPaths = Integer.parseInt(propertyMap.get("tvpb.maxpaths.knr")); + maxPNRPaths = Integer.parseInt(propertyMap.get("tvpb.maxpaths.pnr")); + + } + + public void setupModels() { + + //create a set of UEC objects to use for the components + if(runThreaded) { + threadSafeUECs = new ThreadLocal() { + protected UtilityExpressionCalculator[] initialValue() { + + tvpbLogger.info("Create Thread Safe UECs"); + TVPBDMU tvpbDmu = new TVPBDMU(); + UtilityExpressionCalculator[] uecs = new UtilityExpressionCalculator[5]; + uecs[0] = new UtilityExpressionCalculator(new File(uecFileName), MAZ2TAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[1] = new UtilityExpressionCalculator(new File(uecFileName), OTAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[2] = new UtilityExpressionCalculator(new File(uecFileName), TAP2TAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[3] = new UtilityExpressionCalculator(new File(uecFileName), DTAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[4] = new UtilityExpressionCalculator(new File(uecFileName), TAP2MAZ_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + return(uecs); + } + }; + } else { + TVPBDMU tvpbDmu = new TVPBDMU(); + uecs = new UtilityExpressionCalculator[5]; + uecs[0] = new UtilityExpressionCalculator(new File(uecFileName), MAZ2TAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[1] = new UtilityExpressionCalculator(new File(uecFileName), OTAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[2] = new UtilityExpressionCalculator(new File(uecFileName), TAP2TAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[3] = new UtilityExpressionCalculator(new File(uecFileName), DTAP_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + uecs[4] = new UtilityExpressionCalculator(new File(uecFileName), TAP2MAZ_SHEET, DATA_SHEET, propertyMap, tvpbDmu ); + } + + //create alternatives available array + nAlts = new int[alts+1]; + nAlts[0] = 0; + nAlts[1] = 1; + if(alts==2) { nAlts[2] = 1; } + + } + + public void connectToMatrixServer() { + + //attach process to matrix server + tvpbLogger.info("Connect to Matrix Data Server"); + String matrixServerAddress = propertyMap.get("RunModel.MatrixServerAddress"); + int serverPort = Integer.parseInt(propertyMap.get("RunModel.MatrixServerPort")); + ms = new MatrixDataServerRmi( matrixServerAddress, serverPort, MatrixDataServer.MATRIX_DATA_SERVER_NAME ); + MatrixDataManager mdm = MatrixDataManager.getInstance(); + ms.testRemote(Thread.currentThread().getName()); + mdm.setMatrixDataServerObject( ms ); + } + + public void readTripData() { + + //read trip records + logger.info("Read Trip Records"); + try { + Trip aTripForReadingTrips = new Trip(); + trips = aTripForReadingTrips.readTripsFromCSV(propertyMap); + + //set all trips to use the max walk threshold + for(int j=0; j calculatePathsForATripFJ = new Function1() { + @Override + public Void apply(Trip trip) { + calculatePathsForATrip(trip, true, true, true); + return null; + }; + }; + + //create fork join task and execute it + if(runThreaded) { + DnCFunctionalTask doDNC = new DnCFunctionalTask(trips,calculatePathsForATripFJ,forkJoinMinCalcSize); + new ForkJoinPool().execute(doDNC); + doDNC.getResult(); + } else { + for(int j=0; j()); + + if(walk) { + ArrayList tapPairs = new ArrayList(); + setTVPBDmuValues(tvpbDmu, trip, true, false, false); + calculateWalkPathsForATrip(trip, tapPairs, tvpbDmu); + trip.getTapPairs().addAll(trimPaths(trip, tapPairs, true, false, false)); + } + if(pnr) { + ArrayList tapPairs = new ArrayList(); + setTVPBDmuValues(tvpbDmu, trip, false, true, false); + calculatePnrPathsForATrip(trip, tapPairs, tvpbDmu); + trip.getTapPairs().addAll(trimPaths(trip, tapPairs, false, true, false)); + } + if(knr) { + ArrayList tapPairs = new ArrayList(); + setTVPBDmuValues(tvpbDmu, trip, false, false, true); + calculateKnrPathsForATrip(trip, tapPairs, tvpbDmu); + trip.getTapPairs().addAll(trimPaths(trip, tapPairs, false, false, true)); + } + } + + public void calculateWalkPathsForATrip(Trip trip, ArrayList tapPairs, TVPBDMU tvpbDmu) { + + //TAZ O-D trip distance for getting near taps + float tripDistTaz = mttData.getOTazDTazDistance(trip.otaz, trip.dtaz); + + //walk taps + TapDist[] omazTaps = mttData.getOmazWalkTaps(trip.getOmaz(), Math.min(tripDistTaz, trip.getMaxWalkInFeet())); + TapDist[] dmazTaps = mttData.getDmazWalkTaps(trip.getDmaz(), Math.min(tripDistTaz, trip.getMaxWalkInFeet())); + if(omazTaps!=null & dmazTaps!=null) { + + //calculate walk otaps utils + double[] maz2tapUtils = new double[omazTaps.length]; + double[] otapUtils = new double[omazTaps.length]; + + for(int j=0; j trimPaths(Trip trip, ArrayList tapPairs, boolean walk, boolean pnr, boolean knr) { + + //sort tapPairs by total utility + Collections.sort(tapPairs); + + //take up to n lowest total utility tap pairs + if(trip.getDebugRecord()) { + tvpbLogger.info("Number of initial tap pairs for trip record " + trip.getRecid() + " = " + tapPairs.size()); + } + + //get max paths for mode + int maxPaths = 0; + if(walk) { + maxPaths = maxWalkPaths; + } else if(pnr) { + maxPaths = maxPNRPaths; + } else { + maxPaths = maxKNRPaths; + } + + ArrayList lowestTapPairs = new ArrayList(); + int count = 0; + for(TapPair aTapPair : tapPairs) { + + if(trip.getDebugRecord() & trace) { + tvpbLogger.info("getTotalUtils()[0]= " + aTapPair.getTotalUtils()[0] + " isWalkTapPair=" + aTapPair.isWalkTapPair + ", isPnrTapPair=" + aTapPair.isPnrTapPair + ", isKnrTapPair=" + aTapPair.isKnrTapPair); + } + + lowestTapPairs.add(aTapPair); + count = count + 1; + if(count == maxPaths) { + break; + } + } + + if(trip.getDebugRecord()) { + tvpbLogger.info("Number of trimmed tap pairs for trip record " + trip.getRecid() + " = " + lowestTapPairs.size()); + } + + return(lowestTapPairs); + } + + public void writeOutputData() { + + //output path file name + logger.info("Write output file"); + String projectDirectory = propertyMap.get("Project.Directory"); + String outputPathFileName = propertyMap.get("tvpb.pathfile"); + + PrintWriter pathWriter = null; + try { + pathWriter = new PrintWriter(new File(projectDirectory + outputPathFileName)); + } catch (IOException e) { + logger.error ( "IOException writing path file"); + } + + //write output file header + ArrayList data = new ArrayList(); + data.add("recid"); + data.add("hhid"); + data.add("personid"); + data.add("dayid"); + data.add("tourid"); + data.add("tripid"); + data.add("userclass"); + data.add("cars"); + data.add("age"); + data.add("hhincome"); + data.add("educ"); + data.add("gender"); + data.add("purpose"); + data.add("inbound"); + data.add("tod"); + data.add("otaz"); + data.add("dtaz"); + data.add("omaz"); + data.add("dmaz"); + + data.add("alt"); //tapPair alt + data.add("otap"); + data.add("dtap"); + data.add("otaptaz"); + data.add("dtaptaz"); + data.add("isWalkTapPair"); + data.add("isPnrTapPair"); + data.add("isKnrTapPair"); + + data.add("maz2tapUtils0"); + data.add("otapUtils0"); + data.add("tap2tapUtils0"); + data.add("dtapUtils0"); + data.add("tap2mazUtils0"); + + if(alts==2) { + data.add("maz2tapUtils1"); + data.add("otapUtils1"); + data.add("tap2tapUtils1"); + data.add("dtapUtils1"); + data.add("tap2mazUtils1"); + } + + pathWriter.println(formCsvString(data)); + + //loop through trips and tapPairs and write data; write empty tapPair data if no tapPairs + for(int k=0; k < trips.length; k++) { + for(int j=0; j < Math.max(1, trips[k].tapPairs.size()); j++) { + + ArrayList row = new ArrayList(); + row.add(String.valueOf(trips[k].getRecid())); + row.add(String.valueOf(trips[k].getHhid())); + row.add(String.valueOf(trips[k].getPersonid())); + row.add(String.valueOf(trips[k].getdayid())); + row.add(String.valueOf(trips[k].getTourid())); + row.add(String.valueOf(trips[k].getTripid())); + row.add(String.valueOf(trips[k].getUserClass())); + row.add(String.valueOf(trips[k].getCars())); + row.add(String.valueOf(trips[k].getAge())); + row.add(String.valueOf(trips[k].getHhincome())); + row.add(String.valueOf(trips[k].getEduc())); + row.add(String.valueOf(trips[k].getGender())); + row.add(String.valueOf(trips[k].getPurpose())); + row.add(String.valueOf(trips[k].getInbound())); + row.add(String.valueOf(trips[k].getTod())); + row.add(String.valueOf(trips[k].getOtaz())); + row.add(String.valueOf(trips[k].getDtaz())); + row.add(String.valueOf(trips[k].getOmaz())); + row.add(String.valueOf(trips[k].getDmaz())); + + //has tapPairs + if(trips[k].tapPairs.size() > 0) { + + TapPair aTapPair = trips[k].tapPairs.get(j); + + row.add(String.valueOf(j)); //alt + row.add(String.valueOf(aTapPair.otap)); + row.add(String.valueOf(aTapPair.dtap)); + row.add(String.valueOf(aTapPair.otaptaz)); + row.add(String.valueOf(aTapPair.dtaptaz)); + row.add(String.valueOf(aTapPair.isWalkTapPair)); + row.add(String.valueOf(aTapPair.isPnrTapPair)); + row.add(String.valueOf(aTapPair.isKnrTapPair)); + row.add(String.valueOf(aTapPair.maz2tapUtils[0])); + row.add(String.valueOf(aTapPair.otapUtils[0])); + row.add(String.valueOf(aTapPair.tap2tapUtils[0])); + row.add(String.valueOf(aTapPair.dtapUtils[0])); + row.add(String.valueOf(aTapPair.tap2mazUtils[0])); + + if(alts==2) { + row.add(String.valueOf(aTapPair.maz2tapUtils[1])); + row.add(String.valueOf(aTapPair.otapUtils[1])); + row.add(String.valueOf(aTapPair.tap2tapUtils[1])); + row.add(String.valueOf(aTapPair.dtapUtils[1])); + row.add(String.valueOf(aTapPair.tap2mazUtils[1])); + } + + } else { + + row.add(String.valueOf(j)); //alt + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + + if(alts==2) { + row.add(""); + row.add(""); + row.add(""); + row.add(""); + row.add(""); + } + } + + pathWriter.println(formCsvString(row)); + } + } + pathWriter.close(); + } + + private String formCsvString(List data) + { + char delimiter = ','; + Iterator it = data.iterator(); + StringBuilder sb = new StringBuilder(it.next()); + while(it.hasNext()) + sb.append(delimiter).append(it.next()); + return sb.toString(); + } + + public MazTapTazData getMTTData() { + return(mttData); + } + + public void setMTTData(MazTapTazData mttData) { + this.mttData = mttData; + } + +} diff --git a/src/java/com/pb/cmap/tvpb/Trip.java b/src/java/com/pb/cmap/tvpb/Trip.java new file mode 100644 index 0000000..65fe847 --- /dev/null +++ b/src/java/com/pb/cmap/tvpb/Trip.java @@ -0,0 +1,378 @@ +package com.pb.cmap.tvpb; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.ResourceBundle; + +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.util.ResourceUtil; + +public class Trip { + + int recid; + + int hhid; + int personid; + int dayid; + int tripid; + int tourid; + + int otaz; + int dtaz; + int omaz; + int dmaz; + + int age; + int userClass; + + int cars; + int tod; + int inbound; + + int hhincome; + int educ; + int gender; + int purpose; + + float walkTimeWeight; + float walkSpeed; + float maxWalk; + float persValueOfTime; + + private HashMap userClassByType = new HashMap(); + + boolean debugRecord = false; + + ArrayList tapPairs; + + public Trip() { } + + public int getHhid() { + return hhid; + } + + public void setHhid(int hhid) { + this.hhid = hhid; + } + + public int getPersonid() { + return personid; + } + + public void setPersonid(int personid) { + this.personid = personid; + } + + public int getdayid() { + return dayid; + } + + public void setDayid(int dayid) { + this.dayid = dayid; + } + + public int getTripid() { + return tripid; + } + + public void setTripid(int tripid) { + this.tripid = tripid; + } + + public int getTourid() { + return tourid; + } + + public void setTourid(int tourid) { + this.tourid = tourid; + } + + public int getOtaz() { + return otaz; + } + + public void setOtaz(int otaz) { + this.otaz = otaz; + } + + public int getDtaz() { + return dtaz; + } + + public void setDtaz(int dtaz) { + this.dtaz = dtaz; + } + + public int getOmaz() { + return omaz; + } + + public void setOmaz(int omaz) { + this.omaz = omaz; + } + + public int getDmaz() { + return dmaz; + } + + public void setDmaz(int dmaz) { + this.dmaz = dmaz; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getUserClass() { + return userClass; + } + + public void setUserClass(int userClass) { + this.userClass = userClass; + } + + public int getUserClassByType(String type) { + return userClassByType.get(type); + } + + public void setUserClassByType(String type, int userClass) { + this.userClassByType.put(type, userClass); + } + + public int getCars() { + return cars; + } + + public void setCars(int cars) { + this.cars = cars; + } + + public int getTod() { + return tod; + } + + public void setTod(int tod) { + this.tod = tod; + } + + public int getInbound() { + return inbound; + } + + public void setInbound(int inbound) { + this.inbound = inbound; + } + + public int getHhincome() { + return hhincome; + } + + public void setHhincome(int hhincome) { + this.hhincome = hhincome; + } + + public int getEduc() { + return educ; + } + + public void setEduc(int educ) { + this.educ = educ; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public int getPurpose() { + return purpose; + } + + public void setPurpose(int purpose) { + this.purpose = purpose; + } + + public boolean getDebugRecord() { + return debugRecord; + } + + public void setDebugRecord(boolean debugRecord) { + this.debugRecord = debugRecord; + } + + public int getRecid() { + return recid; + } + + public void setRecid(int recid) { + this.recid = recid; + } + + public float getWalkTimeWeight() { + return walkTimeWeight; + } + + public void setWalkTimeWeight(float walkTimeWeight){ + this.walkTimeWeight =walkTimeWeight; + } + + public float getWalkSpeed() { + return walkSpeed; + } + + public void setWalkSpeed(float walkSpeed) { + this.walkSpeed = walkSpeed; + } + + public float getMaxWalk() { + return maxWalk; + } + + public float getMaxWalkInFeet() { + return maxWalk*5280; + } + + public void setMaxWalk(float maxWalk) { + this.maxWalk = maxWalk; + } + + public void setMaxWalkInFeet(float maxWalk) { + this.maxWalk = maxWalk/5280; + } + + public float getValueOfTime() + { + return persValueOfTime; + } + + public void setValueOfTime(float vot) + { + persValueOfTime = vot; + } + + public ArrayList getTapPairs() { + return(tapPairs); + } + + public ArrayList getWalkTapPairs() { + + ArrayList outTapPairs = new ArrayList(); + for(TapPair aTapPair : tapPairs) { + if(aTapPair.isWalkTapPair) { + outTapPairs.add(aTapPair); + } + } + return(outTapPairs); + } + + public ArrayList getDriveTapPairs() { + + ArrayList outTapPairs = new ArrayList(); + for(TapPair aTapPair : tapPairs) { + if(aTapPair.isKnrTapPair | aTapPair.isPnrTapPair) { + outTapPairs.add(aTapPair); + } + } + return(outTapPairs); + } + + public ArrayList getPnrTapPairs() { + + ArrayList outTapPairs = new ArrayList(); + for(TapPair aTapPair : tapPairs) { + if(aTapPair.isPnrTapPair) { + outTapPairs.add(aTapPair); + } + } + return(outTapPairs); + } + + public ArrayList getKnrTapPairs() { + + ArrayList outTapPairs = new ArrayList(); + for(TapPair aTapPair : tapPairs) { + if(aTapPair.isKnrTapPair) { + outTapPairs.add(aTapPair); + } + } + return(outTapPairs); + } + + public void setTapPairs(ArrayList tapPairs) { + this.tapPairs = tapPairs; + } + + public Trip[] readTripsFromCSV(HashMap propertyMap ) throws IOException { + + // get properties + String tripfile = propertyMap.get("tvpb.tripfile"); + String hhid = propertyMap.get("tvpb.tripfile.hhid"); + String personid = propertyMap.get( "tvpb.tripfile.personid"); + String dayid = propertyMap.get( "tvpb.tripfile.dayid"); + String tourid = propertyMap.get( "tvpb.tripfile.tourid"); + String tripid = propertyMap.get( "tvpb.tripfile.tripid"); + String userclass = propertyMap.get( "tvpb.tripfile.userclass"); + String cars = propertyMap.get( "tvpb.tripfile.cars"); + String age = propertyMap.get( "tvpb.tripfile.age"); + String inbound = propertyMap.get( "tvpb.tripfile.inbound"); + String hhincome = propertyMap.get( "tvpb.tripfile.hhincome"); + String educ = propertyMap.get( "tvpb.tripfile.educ"); + String gender = propertyMap.get( "tvpb.tripfile.gender"); + String purpose = propertyMap.get( "tvpb.tripfile.purpose"); + String tod = propertyMap.get( "tvpb.tripfile.tod"); + String otaz = propertyMap.get( "tvpb.tripfile.otaz"); + String dtaz = propertyMap.get( "tvpb.tripfile.dtaz"); + String omaz = propertyMap.get( "tvpb.tripfile.omaz"); + String dmaz = propertyMap.get( "tvpb.tripfile.dmaz"); + + String debugRecord = propertyMap.get( "tvpb.tripfile.debugRecord"); + + //read CSV + CSVFileReader csvReader = new CSVFileReader(); + TableDataSet trips; + try { + trips = csvReader.readFile( new File(tripfile)); + } catch (IOException e) { + throw new IOException(); + } + + //build array of Trip records + Trip[] outTrips = new Trip[trips.getRowCount()]; + for (int i=0; i methodIndexMap; + + + protected HouseholdIf hh; + protected PersonIf person; + protected TourIf tour; + protected IndexValues dmuIndex; + + protected int homeTazIsUrban; + protected int workTazAreaType; + + protected ModelStructure modelStructure; + + + public AtWorkSubtourFrequencyDMU( ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + } + + + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setPersonObject ( PersonIf persObject ) { + person = persObject; + } + + public void setTourObject ( TourIf tourObject ) { + tour = tourObject; + } + + + + + // DMU methods - define one of these for every @var in the mode choice control file. + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug INMTF UEC" ); + } + + } + + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + public int getNumAutos() { + return hh.getAutoOwnershipModelResult(); + } + + + public int getPersonIsFullTimeWorker() { + return person.getPersonIsFullTimeWorker(); + } + + public int getPersonIsNonworker() { + return person.getPersonIsNonWorkingAdultUnder65() + person.getPersonIsNonWorkingAdultOver65(); + } + + + + + + public void setWorkTazAreaType( int at ){ + workTazAreaType = at; + } + + public int getWorkTazAreaType() { + return workTazAreaType; + } + + + + public int getWorkTourDuration() { + int start = tour.getTourDepartPeriod(); + int end = tour.getTourArrivePeriod(); + return end - start; + } + + /** + * @return number of joint non-mandatory maint, shop, eat-out tours participated in by person. + */ + public int getJointMaintShopEatPerson(){ + int numTours = 0; + TourIf[] jt = hh.getJointTourArray(); + if ( jt != null ) { + int personNum = person.getPersonNum(); + for ( TourIf t : jt ) { + // if joint tour is maint/shop/eat, see if person participated + String tourPurpose = t.getTourPrimaryPurpose(); + if ( tourPurpose.equalsIgnoreCase( modelStructure.getOthMaintPurposeName() ) || + tourPurpose.equalsIgnoreCase( modelStructure.getShoppingPurposeName() ) || + tourPurpose.equalsIgnoreCase( modelStructure.getEatOutPurposeName() ) ) { + byte[] personNums = t.getPersonNumArray(); + for ( int i=0; i < personNums.length; i++ ) { + if (personNums[i] == personNum) { + numTours ++; + break; + } + } + } + } + } + + return numTours; + } + + /** + * @return number of joint non-mandatory discretionary tours participated in by person. + */ + public int getJointDiscrPerson(){ + int numTours = 0; + TourIf[] jt = hh.getJointTourArray(); + if ( jt != null ) { + int personNum = person.getPersonNum(); + for ( TourIf t : jt ) { + // if joint tour is maint/shop/eat, see if person participated + String tourPurpose = t.getTourPrimaryPurpose(); + if ( tourPurpose.equalsIgnoreCase( modelStructure.getOthDiscrPurposeName() ) ) { + byte[] personNums = t.getPersonNumArray(); + for ( int i=0; i < personNums.length; i++ ) { + if (personNums[i] == personNum) { + numTours ++; + break; + } + } + } + } + } + + return numTours; + } + + /** + * @return number of individual non-mandatory maint, shop, escort tours by + * a person who is a full time worker. + */ + public int getIndivMaintShopEscortFt() { + int numTours = 0; + if ( person.getPersonIsFullTimeWorker() == 1 ) + numTours = getNumIndivMaintShopEscortTours(); + return numTours; + } + + /** + * @return number of individual non-mandatory maint, shop, escort tours by + * a person who is a part time worker. + */ + public int getIndivMaintShopEscortPt() { + int numTours = 0; + if ( person.getPersonIsPartTimeWorker() == 1 ) + numTours = getNumIndivMaintShopEscortTours(); + return numTours; + } + + + /** + * @return number of individual non-mandatory discretionary tours by + * a person who is a full time worker. + */ + public int getIndivDiscrFt() { + int numTours = 0; + if ( person.getPersonIsFullTimeWorker() == 1 ) + numTours = getNumIndivDiscrTours(); + return numTours; + } + + /** + * @return number of individual non-mandatory discretionary tours by + * a person who is a part time worker. + */ + public int getIndivDiscrPt() { + int numTours = 0; + if ( person.getPersonIsPartTimeWorker() == 1 ) + numTours = getNumIndivDiscrTours(); + return numTours; + } + + /** + * @return number of individual non-mandatory eat-out tours by person. + */ + public int getIndivEatOut() { + int numTours = 0; + ArrayList tourList = person.getListOfIndividualNonMandatoryTours(); + if ( tourList != null ) { + for ( TourIf t : tourList ) { + String tourPurpose = t.getTourPrimaryPurpose(); + if ( tourPurpose.equalsIgnoreCase( modelStructure.getEatOutPurposeName() ) ) { + numTours ++; + } + } + } + return numTours; + } + + + private int getNumIndivMaintShopEscortTours() { + int numTours = 0; + ArrayList tourList = person.getListOfIndividualNonMandatoryTours(); + if ( tourList != null ) { + for ( TourIf t : tourList ) { + String tourPurpose = t.getTourPrimaryPurpose(); + if ( tourPurpose.equalsIgnoreCase( modelStructure.getOthMaintPurposeName() ) || + tourPurpose.equalsIgnoreCase( modelStructure.getShoppingPurposeName() ) || + tourPurpose.equalsIgnoreCase( modelStructure.getEscortPurposeName() ) ) { + numTours ++; + } + } + } + return numTours; + } + + private int getNumIndivDiscrTours() { + int numTours = 0; + ArrayList tourList = person.getListOfIndividualNonMandatoryTours(); + if ( tourList != null ) { + for ( TourIf t : tourList ) { + String tourPurpose = t.getTourPrimaryPurpose(); + if ( tourPurpose.equalsIgnoreCase( modelStructure.getOthDiscrPurposeName() ) ) { + numTours ++; + } + } + } + return numTours; + } + + public int getWorkTourModeIsSOV() { + boolean tourModeIsSov = modelStructure.getTourModeIsSov( tour.getTourModeChoice() ); + if ( tourModeIsSov ) + return 1; + else + return 0; + } + + public int getNumPersonWorkTours() { + return person.getListOfWorkTours().size(); + } + + /** + * return 1 if person is worker or student with non-mandatory tours; 0 otherwise. + */ + public float getWorkStudNonMandatoryTours () { + if ( person.getPersonIsWorker() == 1 || person.getPersonIsStudent() == 1 ) { + ArrayList tourList = person.getListOfIndividualNonMandatoryTours(); + if ( tourList == null ) + return 0; + else if ( tourList.size() > 0 ) + return 1; + } + return 0; + } + + + + + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/AutoOwnershipChoiceDMU.java b/src/java/com/pb/models/ctrampIf/AutoOwnershipChoiceDMU.java new file mode 100644 index 0000000..2845132 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/AutoOwnershipChoiceDMU.java @@ -0,0 +1,198 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +public class AutoOwnershipChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(AutoOwnershipChoiceDMU.class); + + protected HashMap methodIndexMap; + + + protected HouseholdIf hh; + private IndexValues dmuIndex; + + private double workTourAutoTimeSavings; + private double schoolDriveTourAutoTimeSavings; + private double schoolNonDriveTourAutoTimeSavings; + + //TODO - fix these defaults + private double workAutoDependency = 0; + private double schoolAutoDependency = 0; + private TazDataIf tazDataManager; + + private int[] zoneTableRow; + private float[] access17; + private float[] access18; + + public AutoOwnershipChoiceDMU (){ + dmuIndex = new IndexValues(); + } + + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + + + // DMU methods - define one of these for every @var in the mode choice control file. + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug AO UEC" ); + } + + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public void setupTazDataManager(TazDataIf tazDataManager) { + this.tazDataManager = tazDataManager; + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned us 0-based indexing + access17 = tazDataManager.getAccess17Accessibity(); + access18 = tazDataManager.getAccess18Accessibity(); + + } + + public double getAccess17() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return access17[index]; + } + + public double getAccess18() { + int index = zoneTableRow[dmuIndex.getOriginZone()] - 1; + return access18[index]; + } + + public int getSize() { + return hh.getSize(); + } + + public int getNumChildrenUnder16() { + return hh.getNumChildrenUnder16(); + } + + public int getHhBldgsz() { + return hh.getHhBldgsz(); + } + + public int getDrivers() { + return hh.getDrivers(); + } + + public int getWorkers() { + return hh.getWorkers(); + } + + public int getStudents() { + return hh.getNumStudents(); + } + + public int getNumPersons16to17() { + return hh.getNumPersons16to17(); + } + + public int getNumPersons18to24() { + return hh.getNumPersons18to24(); + } + + public int getNumPersons65to79() { + return hh.getNumPersons65to79(); + } + + public int getNumPersons80plus() { + return hh.getNumPersons80plus(); + } + + public void setWorkTourAutoTimeSavings( double value ) { + workTourAutoTimeSavings = value; + } + + public double getWorkTourAutoTimeSavings() { + return workTourAutoTimeSavings; + } + + public void setSchoolDriveTourAutoTimeSavings( double value ) { + schoolDriveTourAutoTimeSavings = value; + } + + public double getSchoolDriveTourAutoTimeSavings() { + return schoolDriveTourAutoTimeSavings; + } + + public void setSchoolNonDriveTourAutoTimeSavings( double value ) { + schoolNonDriveTourAutoTimeSavings = value; + } + + public double getSchoolNonDriveTourAutoTimeSavings() { + return schoolNonDriveTourAutoTimeSavings; + } + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + public double getWorkAutoDependency() { + return workAutoDependency; + } + public double getSchoolAutoDependency() { + return schoolAutoDependency; + } + + public void setWorkAutoDependency(double workAutoDependency) { + this.workAutoDependency = workAutoDependency; + } + public void setSchoolAutoDependency(double schoolAutoDependency) { + this.schoolAutoDependency = schoolAutoDependency; + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/CoordinatedDailyActivityPatternDMU.java b/src/java/com/pb/models/ctrampIf/CoordinatedDailyActivityPatternDMU.java new file mode 100644 index 0000000..b846aec --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/CoordinatedDailyActivityPatternDMU.java @@ -0,0 +1,266 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +/** + * Decision making unit object for the Coordinated Daily Activity Pattern Model. This + * DMU contains all the getters specified in the UEC, i.e. all the "@" variables. + * + * @author D. Ory + * + */ +public class CoordinatedDailyActivityPatternDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(CoordinatedDailyActivityPatternDMU.class); + + protected HashMap methodIndexMap; + + + protected IndexValues dmuIndex; + + protected HouseholdIf householdObject; + protected PersonIf personA, personB, personC; + + + + public CoordinatedDailyActivityPatternDMU(){ + dmuIndex = new IndexValues(); + } + + public void setDmuIndexValues(int zoneId) { + dmuIndex.setZoneIndex(zoneId); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( householdObject.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug CDAP UEC" ); + } + + } + + public IndexValues getIndexValues() { + return dmuIndex; + } + + public void setHousehold(HouseholdIf passedInHouseholdObject){ + + householdObject = passedInHouseholdObject; + + // set the household index + dmuIndex.setHHIndex(passedInHouseholdObject.getHhId()); + + // set the home zone as the zone index + dmuIndex.setZoneIndex(passedInHouseholdObject.getHhTaz()); + } + + public void setPersonA(PersonIf passedInPersonA){ + this.personA = passedInPersonA; + } + + public void setPersonB(PersonIf passedInPersonB){ + this.personB = passedInPersonB; + } + + public void setPersonC(PersonIf passedInPersonC){ + this.personC = passedInPersonC; + } + + // full-time worker + public int getFullTimeWorkerA(){ + return(personA.getPersonTypeIsFullTimeWorker()); + } + + public int getFullTimeWorkerB(){ + return(personB.getPersonTypeIsFullTimeWorker()); + } + + public int getFullTimeWorkerC(){ + return(personC.getPersonTypeIsFullTimeWorker()); + } + // part-time worker + public int getPartTimeWorkerA(){ + return(personA.getPersonTypeIsPartTimeWorker()); + } + + public int getPartTimeWorkerB(){ + return(personB.getPersonTypeIsPartTimeWorker()); + } + + public int getPartTimeWorkerC(){ + return(personC.getPersonTypeIsPartTimeWorker()); + } + + // university student + public int getUniversityStudentA(){ + return(personA.getPersonIsUniversityStudent()); + } + + public int getUniversityStudentB(){ + return(personB.getPersonIsUniversityStudent()); + } + + public int getUniversityStudentC(){ + return(personC.getPersonIsUniversityStudent()); + } + + // non-working adult + public int getNonWorkingAdultA(){ + return(personA.getPersonIsNonWorkingAdultUnder65()); + } + + public int getNonWorkingAdultB(){ + return(personB.getPersonIsNonWorkingAdultUnder65()); + } + + public int getNonWorkingAdultC(){ + return(personC.getPersonIsNonWorkingAdultUnder65()); + } + + // retired + public int getRetiredA(){ + return(personA.getPersonIsNonWorkingAdultOver65()); + } + + public int getRetiredB(){ + return(personB.getPersonIsNonWorkingAdultOver65()); + } + + public int getRetiredC(){ + return(personC.getPersonIsNonWorkingAdultOver65()); + } + + // driving age school child + public int getDrivingAgeSchoolChildA(){ + return(personA.getPersonIsStudentDriving()); + } + + public int getDrivingAgeSchoolChildB(){ + return(personB.getPersonIsStudentDriving()); + } + + public int getDrivingAgeSchoolChildC(){ + return(personC.getPersonIsStudentDriving()); + } + + // non-driving school-age child + public int getPreDrivingAgeSchoolChildA(){ + return(personA.getPersonIsStudentNonDriving()); + } + + public int getPreDrivingAgeSchoolChildB(){ + return(personB.getPersonIsStudentNonDriving()); + } + + public int getPreDrivingAgeSchoolChildC(){ + return(personC.getPersonIsStudentNonDriving()); + } + + // pre-school child + public int getPreSchoolChildA(){ + return(personA.getPersonIsPreschoolChild()); + } + + public int getPreSchoolChildB(){ + return(personB.getPersonIsPreschoolChild()); + } + + public int getPreSchoolChildC(){ + return(personC.getPersonIsPreschoolChild()); + } + + // age + public int getAgeA(){ + return(personA.getAge()); + } + + // female + public int getFemaleA(){ + return(personA.getPersonIsFemale()); + } + + // household more cars than workers + public int getMoreCarsThanWorkers(){ + + int workers = householdObject.getWorkers(); + int autos = householdObject.getAutoOwnershipModelResult(); + + if(autos>workers) return 1; + return 0; + + } + + // household fewer cars than workers + public int getFewerCarsThanWorkers(){ + + int workers = householdObject.getWorkers(); + int autos = householdObject.getAutoOwnershipModelResult(); + + if(autos logitModelList; + + // DMU for the UEC + protected CoordinatedDailyActivityPatternDMU dmuObject; + + protected String cdapResultsFileName; + + // re-ordered collection of households + protected PersonIf[] cdapPersonArray; + + // Four separate UECs to compute segments of the utility + protected UtilityExpressionCalculator onePersonUec, twoPeopleUec, threePeopleUec, allMemberInteractionUec; + + // summary collections + protected HashMap> countByHhSizeAndPattern; + protected HashMap> countByPersonTypeAndActivity; + + + + /** + * Constructor sets up a logit model for each of the 5 possible household sizes and reads in + * each of the four UEC model tabs. + * + * @param uecFileName - should contain a tab for each of the four utility segments, as well + * as one for the data + * @param resourceBundle - should contain any references made in the UEC file (not used for anything + * other than the UEC call) + */ + public CoordinatedDailyActivityPatternModel(String uecFileName, ResourceBundle resourceBundle){ + + createLogitModels(); + setUpModel(uecFileName, resourceBundle); + + } + + + + /** + * Loops through the households in the HouseholdDataManager, gets the coordinated daily + * activity pattern for each person in the household, and writes a text file with hhid, + * personid, persnum, and activity pattern. + * + * @param householdDataManager + */ + public void saveResults(HouseholdDataManagerIf householdDataManager, String projectDirectory){ + + FileWriter writer; + if ( cdapResultsFileName != null ) { + + cdapResultsFileName = projectDirectory + cdapResultsFileName; + + try { + writer = new FileWriter(new File(cdapResultsFileName)); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred opening CDAP results file: %s.", cdapResultsFileName ) ); + throw new RuntimeException(e); + } + + try { + writer.write ( "HHID,PersonID,PersonNum,ActivityString\n" ); + } + catch(IOException e){ + logger.fatal( "Exception occurred writing CDAP header in results file." ) ; + throw new RuntimeException(e); + } + + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray(); + + for(int i=1; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + int hhid = household.getHhId(); + + // get the pattern for each person + PersonIf[] personArray = household.getPersons(); + for( int j=1; j < personArray.length; j++ ) { + + int persId = personArray[j].getPersonId(); + int persNum = personArray[j].getPersonNum(); + String activityString = personArray[j].getCdapActivity(); + + try { + writer.write ( String.format("%d,%d,%d,%s\n", hhid, persId, persNum, activityString )); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred writing CDAP results file, hhid=%d, persId=%d, persNum=%d", hhid, persId, persNum ) ); + throw new RuntimeException(e); + } + + } // j (person loop) + + } + + + try { + writer.close(); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred closing CDAP results file: %s.", cdapResultsFileName ) ); + throw new RuntimeException(e); + } + + } + + } + + + + /** + * Loops through the households in the HouseholdDataManager, applies the coordinated daily + * activity pattern model, sets the pattern for the selected household (which, in turn, sets + * the activity for each person), and summarizes the results by household size and pattern, as + * well as by person type and activity. + * + * @param householdDataManager + */ + public void applyModel(HouseholdDataManagerIf householdDataManager){ + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray(); + + // initialize the results maps/lists + countByHhSizeAndPattern = new HashMap>(); + countByPersonTypeAndActivity = new HashMap>(); + + //TODO: check the indexing - 1 based or 0-based? + // loop through households (1-based array) + for(int i=1; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + + // give some feedback + if(i%500000==0) logger.info("... Processing household ID: "+household.getHhId()); + + // get the activity pattern choice + String pattern = getCoordinatedDailyActivityPatternChoice(household); + + // set the pattern for the household + household.setCoordinatedDailyActivityPatternResult( pattern ); + + // set the pattern for each person and count by person type + PersonIf[] personArray = household.getPersons(); + for(int j=1;j activityCountMap = countByPersonTypeAndActivity.get(personTypeString); + + // check if the activity is in the activity map + if(activityCountMap.containsKey(activityString)){ + int currentCount = activityCountMap.get(activityString); + currentCount++; + activityCountMap.put(activityString, currentCount); + countByPersonTypeAndActivity.put(personTypeString, activityCountMap); + } + else{ + activityCountMap.put(activityString, 1); + countByPersonTypeAndActivity.put(personTypeString, activityCountMap); + } + + + } + else{ + HashMap activityCountMap = new HashMap(); + activityCountMap.put(activityString, 1); + countByPersonTypeAndActivity.put(personTypeString, activityCountMap); + + } // is personType in map if + + } // j (person loop) + + + // count each type of pattern string by hhSize + if(countByHhSizeAndPattern.containsKey(pattern.length())){ + HashMap patternCountMap = countByHhSizeAndPattern.get(pattern.length()); + if(patternCountMap.containsKey(pattern)){ + int currentCount = patternCountMap.get(pattern); + currentCount++; + patternCountMap.put(pattern, currentCount); + } + else{ + patternCountMap.put(pattern, 1); + countByHhSizeAndPattern.put(pattern.length(), patternCountMap); + } + } + else{ + HashMap patternCountMap = new HashMap(); + patternCountMap.put(pattern, 1); + countByHhSizeAndPattern.put(pattern.length(), patternCountMap); + + } // is personType in map if + + // log results for debug households + if(household.getDebugChoiceModels()){ + + logger.info(" "); + logger.info("CDAP Chosen Pattern by Person Type"); + logger.info("CDAP # FT W PT W UNIV NONW RETR SCHD SCHN PRES"); + logger.info("------ ---- ---- ---- ---- ---- ---- ---- ----"); + + String bString = ""; + for(int j=1;j hhSizeKeySet = countByHhSizeAndPattern.keySet(); + Integer[] hhSizeKeyArray = new Integer[hhSizeKeySet.size()]; + hhSizeKeySet.toArray(hhSizeKeyArray); + Arrays.sort(hhSizeKeyArray); + + int total = 0; + for(int i=0;i patternMap = countByHhSizeAndPattern.get(hhSizeKeyArray[i]); + Set patternKeySet = patternMap.keySet(); + String[] patternKeyArray = new String[patternKeySet.size()]; + patternKeySet.toArray(patternKeyArray); + Arrays.sort(patternKeyArray); + for(int j=0;jj because if we have 1,2 for person 1, we don't also want 2,1; that's the + // same combination of two people + if(i>j) continue; + + PersonIf personB = getCdapPerson(j+1); + + // set the two person level dmu variables + dmuObject.setPersonB(personB); + + // compute the two people utilities + double[] twoPersonUtilities = twoPeopleUec.solve(dmuObject.getIndexValues(),dmuObject,availability); + + // log these utilities for trace households + if(householdObject.getDebugChoiceModels()){ + + String stringToLog = String.format("%-30s%9d%9d%9s", "TwoPeople",(i+1),(j+1),"--"); + + for(int k=0;kk because if we have 1,2,3 for person 1, we don't also want 1,3,2; that's the + // same combination of three people + if(j>k) continue; + + PersonIf personC = getCdapPerson(k+1); + + // set the three level dmu variables + dmuObject.setPersonC(personC); + + // compute the three person utilities + double[] threePersonUtilities = threePeopleUec.solve(dmuObject.getIndexValues(),dmuObject,availability); + + // log these utilities for trace households + if(householdObject.getDebugChoiceModels()){ + + String stringToLog = String.format("%-30s%9d%9d%9d", "ThreePeople",(i+1),(j+1),(k+1)); + + for(int l=0;lMAX_MODEL_HH_SIZE){ + + String allMembersChosenPattern = applyModelForExtraHhMembers(householdObject,firstFiveChosenName); + + // re-order the activities by the original order of persons + String finalHhPattern = ""; + String[] finalHhPatternActivities = new String[cdapPersonArray.length]; + for ( int i=1; i < cdapPersonArray.length; i++ ) { + int k = cdapPersonArray[i].getPersonNum(); + finalHhPatternActivities[k] = allMembersChosenPattern.substring( i-1, i ); + } + + for ( int i=1; i < cdapPersonArray.length; i++ ) + finalHhPattern += finalHhPatternActivities[i]; + + return finalHhPattern; + + } + + + + // no need to re-order the activities - hhsize <= MAX_MODEL_HH_SIZE have original order of persons + return firstFiveChosenName; + + + } + /** + * Applies a simple, segmented fixed-distribution model for members of households with more than + * 5 people who are not included in the CDAP model. The choices of the additional household + * members are independent of each other, but dependent on the pattern choice for the 5 + * modeled household members. + * + * @param householdObject + * @param patternStringForOtherHhMembers + * @return the pattern for the entire household, including the 5-member pattern chosen by the + * logit model and the additional members chosen by the fixed-distribution model. + * + */ + private String applyModelForExtraHhMembers(HouseholdIf householdObject, String patternStringForOtherHhMembers){ + + String allMembersPattern = patternStringForOtherHhMembers; + + // get the persons not yet modeled + PersonIf[] personArray = getPersonsNotModeledByCdap(MAX_MODEL_HH_SIZE); + + // person array is 1-based to be consistent with other person arrays + for(int i=1;i propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + onePersonUec = new UtilityExpressionCalculator(new File(uecFileName),UEC_ONE_PERSON,UEC_DATA_PAGE,propertyMap,(VariableTable)dmuObject); + twoPeopleUec = new UtilityExpressionCalculator(new File(uecFileName),UEC_TWO_PERSON,UEC_DATA_PAGE,propertyMap,(VariableTable)dmuObject); + threePeopleUec = new UtilityExpressionCalculator(new File(uecFileName),UEC_THREE_PERSON,UEC_DATA_PAGE,propertyMap,(VariableTable)dmuObject); + allMemberInteractionUec = new UtilityExpressionCalculator(new File(uecFileName),UEC_ALL_PERSON,UEC_DATA_PAGE,propertyMap,(VariableTable)dmuObject); + + } + + /** + * Prepares a separate logit model for households of size 1, 2, 3, 4, and 5. Each model + * has 3^n alternatives, where n is the household size. The models are cleared and re-used + * for each household of the specified size. + * + */ + private void createLogitModels(){ + + // new the collection of logit models + logitModelList = new ArrayList(MAX_MODEL_HH_SIZE); + + // build a model for each HH size + for(int i=0;i cdapPersonArray.length - 1 ) { + logger.fatal( String.format("persNum value = %d is out of range for hhSize = %d", persNum, cdapPersonArray.length - 1) ); + throw new RuntimeException(); + } + + return cdapPersonArray[persNum]; + } + + /** + * Method returns an array of persons not modeled by the CDAP model (i.e. persons 6 to X, when + * ordered by the reOrderPersonsForCdap method + * @param personsModeledByCdap + * @return + */ + public PersonIf[] getPersonsNotModeledByCdap(int personsModeledByCdap){ + + // create a 1-based person array to be consistent + PersonIf[] personArray = new PersonIf[cdapPersonArray.length - personsModeledByCdap]; + + for(int i=1;i methodIndexMap; + + + protected HouseholdIf hh; + protected PersonIf person; + protected IndexValues dmuIndex = null; + protected String dmuLabel = "Origin Location"; + + protected DestChoiceSize dcSizeObj; + + protected int[] altToZone; + protected int[] altToSubZone; + + + public DcSoaDMU( TazDataIf tazDataManager ){ + altToZone = tazDataManager.getAltToZoneArray(); + altToSubZone = tazDataManager.getAltToSubZoneArray(); + + dmuIndex = new IndexValues(); + } + + + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug DC SOA UEC" ); + } + + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setPersonObject ( PersonIf personObject ) { + person = personObject; + } + + public void setDestChoiceSizeObject ( DestChoiceSize dcSizeObj ) { + this.dcSizeObj = dcSizeObj; + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + public HouseholdIf getHouseholdObject() { + return hh; + } + + protected double getLnDcSizeForPurpSegAlt( int alt, String purposeString ){ + + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + + int purposeIndex = dcSizeObj.getDcSizeArrayPurposeIndex(purposeString); + double size = dcSizeObj.getDcSize(purposeIndex, zone, subzone); + + double logSize = 0.0; + if ( size > 0 ) + logSize = Math.log(size + 1); + + return logSize; + + } + + public String getDmuLabel() { + return dmuLabel; + } + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} + + diff --git a/src/java/com/pb/models/ctrampIf/Definitions.java b/src/java/com/pb/models/ctrampIf/Definitions.java new file mode 100644 index 0000000..270ff5d --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/Definitions.java @@ -0,0 +1,20 @@ +package com.pb.models.ctrampIf; + +/** + * This class holds definitions that are inherant in CT-RAMP based models including: + * person types + * tour category types + * purposes + * activity types + * + * @author Jim + * + */ +public class Definitions { + + // Coordinated daily activity pattern type definitions + public static final String MANDATORY_PATTERN = "M"; + public static final String NONMANDATORY_PATTERN = "N"; + public static final String HOME_PATTERN = "H"; + +} diff --git a/src/java/com/pb/models/ctrampIf/DestChoiceDMU.java b/src/java/com/pb/models/ctrampIf/DestChoiceDMU.java new file mode 100644 index 0000000..60cf31a --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/DestChoiceDMU.java @@ -0,0 +1,243 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + + +public abstract class DestChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(DestChoiceDMU.class); + + protected HashMap methodIndexMap; + + public DestChoiceSize dcSizeObj; + + public HouseholdIf hh; + public PersonIf person; + public TourIf tour; + public IndexValues dmuIndex = null; + + public int[] altToZone; + public int[] altToSubZone; + + public double[][][] modeChoiceLogsums; + public double[][] dcSoaCorrections; + + public ModelStructure modelStructure; + + + public DestChoiceDMU ( TazDataIf tazDataManager, ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + initDmuObject( tazDataManager ); + } + + + abstract public void setMcLogsum( int index, int zone, int subzone, double logsum ); + + + + + private void initDmuObject( TazDataIf tazDataManager ) { + + dmuIndex = new IndexValues(); + + altToZone = tazDataManager.getAltToZoneArray(); + altToSubZone = tazDataManager.getAltToSubZoneArray(); + + int numZones = tazDataManager.getNumberOfZones(); + int numSubZones = tazDataManager.getNumberOfSubZones(); + + int numMcLogsumIndices = modelStructure.getPeriodCombinationIndices().length; + modeChoiceLogsums = new double[numMcLogsumIndices][numZones+1][numSubZones]; + dcSoaCorrections = new double[numZones+1][numSubZones]; + + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setPersonObject ( PersonIf personObject ) { + person = personObject; + } + + public void setTourObject ( TourIf tour ) { + this.tour = tour; + } + + public void setDestChoiceSize ( DestChoiceSize dcSizeObj ) { + this.dcSizeObj = dcSizeObj; + } + + + public void setDcSoaCorrections( int zone, int subzone, double correction ){ + dcSoaCorrections[zone][subzone] = correction; + } + + + + + + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug DC UEC" ); + } + + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public PersonIf getPersonObject() { + return person; + } + + + + + // DMU methods - define one of these for every @var in the mode choice control file. + + protected double getDcSoaCorrectionsAlt( int alt ){ + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + return dcSoaCorrections[zone][subzone]; + } + + protected double getMcLogsumDestAlt( int index, int zone, int subZone ) { + return modeChoiceLogsums[index][zone][subZone]; + } + + protected double getLnDcSizeForPurposeAlt( int alt, String purposeString ){ + + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + + int purposeIndex = dcSizeObj.getDcSizeArrayPurposeIndex(purposeString); + double size = dcSizeObj.getDcSize(purposeIndex, zone, subzone); + + double logSize = 0.0; + if ( size > 0 ) + logSize = Math.log(size); + + return logSize; + + } + + + + + protected int getZonalShortWalkAccessOrig() { + if ( hh.getHhWalkSubzone() == 1 ) + return 1; + else + return 0; + } + + + protected int getZonalShortWalkAccessDestAlt( int alt ) { + int subzone = altToSubZone[alt]; + if ( subzone == 1 ) + return 1; + else + return 0; + } + + protected int getAutos() { + return hh.getAutoOwnershipModelResult(); + } + + protected int getWorkers() { + return hh.getWorkers(); + } + + protected int getNumChildrenUnder16() { + return hh.getNumChildrenUnder16(); + } + + protected int getNumChildrenUnder19() { + return hh.getNumChildrenUnder19(); + } + + protected int getAge() { + return person.getAge(); + } + + protected int getFullTimeWorker() { + if ( person.getPersonIsFullTimeWorker() == 1 ) + return 1; + else + return 0; + } + + protected int getWorkTaz() { + return person.getUsualWorkLocation(); + } + + protected int getPersonIsFemale() { + return person.getPersonIsFemale(); + } + + protected int getWorkTourModeIsSOV() { + boolean tourModeIsSov = modelStructure.getTourModeIsSov( tour.getTourModeChoice() ); + if ( tourModeIsSov ) + return 1; + else + return 0; + } + + + protected int getTourIsJoint() { + return tour.getTourCategoryIndex() == ModelStructure.JOINT_NON_MANDATORY_CATEGORY_INDEX ? 1 : 0; + } + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} + + diff --git a/src/java/com/pb/models/ctrampIf/DestChoiceSize.java b/src/java/com/pb/models/ctrampIf/DestChoiceSize.java new file mode 100644 index 0000000..8349abb --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/DestChoiceSize.java @@ -0,0 +1,1342 @@ +package com.pb.models.ctrampIf; + +import java.io.*; +import java.text.DecimalFormat; +import java.util.*; + +import org.apache.log4j.Logger; + +import com.pb.common.datafile.*; +import com.pb.common.util.ResourceUtil; + +/** + * Handles building and storing destination choice size variables + * + */ + +public class DestChoiceSize implements Serializable { + + private transient Logger logger = Logger.getLogger(DestChoiceSize.class); + + + public static final String PROPERTIES_DC_SIZE_INPUT = "UsualWorkAndSchoolLocationChoice.SizeCoefficients.InputFile"; + public static final String PROPERTIES_DC_SIZE_OUTPUT = "UsualWorkAndSchoolLocationChoice.SizeTerms.OutputFile"; + public static final String PROPERTIES_DC_SHADOW_OUTPUT = "UsualWorkAndSchoolLocationChoice.ShadowPricing.OutputFile"; + public static final String PROPERTIES_DC_SHADOW_NITER = "UsualWorkAndSchoolLocationChoice.ShadowPricing.MaximumIterations"; + + protected HashMap> dcSizePurposeSegmentIndexMap; + protected HashMap>> dcSizeCoeffsByPurposeAndSegmentMap; + protected String[] dcSizeVariablesList; + + + // 1st dimension is an index for the set of DC Size variables used in Sample of Alternative choice and destination choice, + // 2nd dimension is zone number (1,...,numZones), 3rd dimension walk subzone index is 0: no walk %, 1: shrt %, 2: long %. + protected double[][][] dcSize; + protected double[][][] originalSize; + protected double[][][] originalAdjSize; + protected double[][][] scaledSize; + protected double[][][] balanceSize; + protected double[][][] previousSize; + protected double[][][] shadowPrice; + + protected int maxShadowPriceIterations; + + protected String destChoiceWorkerAdjustmentFileName = "Not yet implemented"; + protected String dcShadowOutputFileName; + protected String dcSizeTermOutputFileName; + + protected boolean dcSizeCalculated = false; + + protected ModelStructure modelStructure; + protected TazDataIf tazDataManager; + + + protected String[] subZoneNames; + protected int numSubZones; + protected int numZones; + + protected int[] areaType; + protected int[] zoneTableRow; + + protected String projectDirectory; + protected String tourCategory; + + + + + public DestChoiceSize( ModelStructure modelStructure, TazDataIf tazDataManager){ + + // establish the model structure + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + numZones = tazDataManager.getNumberOfZones(); + numSubZones = tazDataManager.getNumberOfSubZones(); + subZoneNames = tazDataManager.getSubZoneNames(); + + } + + + + public void setupDestChoiceSize( ResourceBundle rb, String projectDirectory, String tourCategory ){ + + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(rb); + setupDestChoiceSize( propertyMap, projectDirectory, tourCategory ); + + } + + + public void setupDestChoiceSize( HashMap propertyMap, String projectDirectory, String tourCategory ){ + + this.projectDirectory = projectDirectory; + this.tourCategory = tourCategory; + + if(propertyMap.containsKey( PROPERTIES_DC_SIZE_OUTPUT )) { + dcSizeTermOutputFileName = projectDirectory + propertyMap.get( PROPERTIES_DC_SIZE_OUTPUT ); + } + + dcShadowOutputFileName = projectDirectory + propertyMap.get( PROPERTIES_DC_SHADOW_OUTPUT ); + + // get the number of shadow price iterations + maxShadowPriceIterations = Integer.parseInt( propertyMap.get( PROPERTIES_DC_SHADOW_NITER ) ); + + // read the dc size coefficients file + String destChoiceSizeFileName = projectDirectory + propertyMap.get( PROPERTIES_DC_SIZE_INPUT ); + readDcSizeCoeffsArray(destChoiceSizeFileName); + + } + + + public boolean getDcSizeCalculated() { + return dcSizeCalculated; + } + + + public void setDcSizeCalculated( boolean dcSizeCalculatedArg ) { + dcSizeCalculated = dcSizeCalculatedArg; + } + + + public int getMaxShadowPriceIterations() { + return maxShadowPriceIterations; + } + + + /** + * Read the size variable coefficient values from the file whose name is passed in. + * Store the values for later calculation, and check the consistency between purpose, segment values in the file + * and those defined in the modelStructure object. Also check consistency between coefficient field names + * and zonal table field names. + * @param dcSizeVariablesFileName is the file name for the destination choice size coefficient values. + */ + private void readDcSizeCoeffsArray(String dcSizeVariablesFileName){ + + // read in the csv table + TableDataSet coeffTable; + try{ + + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + reader.setDelimSet( "," + reader.getDelimSet() ); + coeffTable = reader.readFile(new File( dcSizeVariablesFileName )); + + } + catch(Exception e){ + logger.fatal( String.format( "Exception occurred reading DC Size coefficients data file: %s into TableDataSet object.", dcSizeVariablesFileName ) ); + throw new RuntimeException(); + } + + + // declare a map to get the dcSize[][][] 1st index from the purpose/segment + dcSizePurposeSegmentIndexMap = new HashMap>(); + + // prepare the coefficients map and purpose/segment lists + dcSizeCoeffsByPurposeAndSegmentMap = new HashMap>>(); + + + // fetch the purpose and segment field name strings + String purposeFieldName = modelStructure.getDcSizeCoeffPurposeFieldName(); + String segmentFieldName = modelStructure.getDcSizeCoeffSegmentFieldName(); + + + // loop through each row, check for consistent variable naming with modelStructure and zonal table, and store the values in the maps. + String[] columnLabels = coeffTable.getColumnLabels(); + for(int i=0; i < coeffTable.getRowCount(); i++){ + + // set the row number (table data is one-based) + int rowNumber = i+1; + + String purposeString = coeffTable.getStringValueAt(rowNumber, purposeFieldName); + String segmentString = coeffTable.getStringValueAt(rowNumber, segmentFieldName); + + if ( modelStructure.isValidDcSizePurposeSegment( purposeString, segmentString ) ) { + + // new the map and list to store the coefficients + HashMap sizeCoeffsByVariableNameMap = new HashMap(columnLabels.length-2); + dcSizeVariablesList = new String[columnLabels.length-2]; + + // loop through the rest of the columns and store the coefficients + int varCount = 0; + for( String fieldName : columnLabels ) { + + // skip the purpose and segment columns + if( fieldName.equalsIgnoreCase(purposeFieldName)) continue; + if( fieldName.equalsIgnoreCase(segmentFieldName)) continue; + + // make sure the field name is also defined in the zonal table + if ( ! tazDataManager.isValidZoneTableField(fieldName) ) { + logger.error ( String.format("the fieldName: %s, defined in the header row in column: %d, of file: %s,", fieldName, (varCount+2), dcSizeVariablesFileName) ); + logger.error ( String.format("does not match any of the zonal data table field names defined in the %s object:", tazDataManager.getClass().getName()) ); + logger.error ( String.format(" %16s", "Taz Data Fields:")); + for ( String name : tazDataManager.getZoneDataTableColumnLabels() ) + logger.error ( String.format(" %s16", name)); + throw new RuntimeException(); + } + + + float coeffValue = coeffTable.getValueAt( rowNumber, fieldName ); + sizeCoeffsByVariableNameMap.put( fieldName, coeffValue ); + + // keep them in an array for later indexing + dcSizeVariablesList[varCount++] = fieldName; + + } + + // get the coeffs map for the purpose (or create one), then store a map for segments + String purpKey = purposeString.toLowerCase(); + String segKey = segmentString.toLowerCase(); + HashMap> segmentMap = null; + if ( dcSizeCoeffsByPurposeAndSegmentMap.containsKey(purpKey) ) + segmentMap = dcSizeCoeffsByPurposeAndSegmentMap.get( purpKey ); + else + segmentMap = new HashMap>(); + segmentMap.put( segKey, sizeCoeffsByVariableNameMap ); + dcSizeCoeffsByPurposeAndSegmentMap.put( purpKey, segmentMap ); + + + // the TableDataSet row id will be the index for the dcSize array calculated. + HashMap indexMap = null; + if ( dcSizePurposeSegmentIndexMap.containsKey(purpKey) ) + indexMap = dcSizePurposeSegmentIndexMap.get( purpKey ); + else + indexMap = new HashMap(); + indexMap.put( segKey, i ); + + } + + } // row loop + + } + + + public void calculateDcSize() { + + // initialize dcSize array used in DC model + String[] dcSizeArrayPurposes = modelStructure.getDcSizeArrayPurposeStrings(); + + // allocate the dcSize array for purposes that match the tourCategory for which size is being calculated. + dcSize = new double[dcSizeArrayPurposes.length][][]; + int purposeIndexOffset = modelStructure.getDcSizeArrayCategoryIndexOffset(tourCategory); + int end = purposeIndexOffset + modelStructure.getNumDcSizeArrayCategorySegments(tourCategory); + for ( int i=purposeIndexOffset; i < end; i++ ) { + dcSize[i] = new double[numZones+1][numSubZones]; + } + + // loop through the variables used in the size calculation and get the columns from the zonal data table + float[][] tempVariableTable = new float[dcSizeVariablesList.length][]; + for( int l=0; l < dcSizeVariablesList.length; l++ ) { + String variableName = dcSizeVariablesList[l]; + tempVariableTable[l] = tazDataManager.getZoneTableFloatColumn( variableName ); + } + + + + // get the dcSize segments for which size is calculated + String[] dcSizeSegmentPurposes = modelStructure.getDcSizeSegmentStrings(); + + // get the offset and number of segments to calculate + purposeIndexOffset = modelStructure.getDcSizeSegmentCategoryIndexOffset(tourCategory); + end = purposeIndexOffset + modelStructure.getNumDcSizeSegmentCategorySegments(tourCategory); + + // loop through the purpose and segments to create the size terms + for( int p=purposeIndexOffset; p < end; p++ ){ + + // get the coefficients map + int underscoreIndex = dcSizeSegmentPurposes[p].indexOf('_'); + String purposeString = dcSizeSegmentPurposes[p].substring(0,underscoreIndex); + String segmentString = dcSizeSegmentPurposes[p].substring(underscoreIndex+1); + + HashMap> segmentMap = dcSizeCoeffsByPurposeAndSegmentMap.get( purposeString ); + if (segmentMap==null) logger.error("Could not find purpose " + purposeString + " in dcSizeCeoffs maps."); + + HashMap coefficientsMap = segmentMap.get( segmentString ); + if (coefficientsMap==null) logger.error("Could not find segment " + segmentString + + " of purpose " + purposeString + " in dcSizeCeoffs maps."); + + float[] tempCoefficients = new float[dcSizeVariablesList.length]; + for( int l=0; l < dcSizeVariablesList.length; l++ ) { + String variableName = dcSizeVariablesList[l]; + tempCoefficients[l] = coefficientsMap.get(variableName); + } + + //TODO: make sure zone number and tabledata row indices are used correctly and appropriately + + //TODO: this is not generic - it's project specific with area type segmentation -- need to resolve this better. + + // if a dc size segment is areatype based, the size is calculated only if the zone is within that area type. + // otherwise the size is calcualted for every zone. + if ( isSegmentAreaTypeBased(segmentString) ){ + + // loop through the zones and sub-zones to compute the size terms + for( int k=0; k < numZones; k++ ) { + + int zoneNumber = k + 1; + double totalZonalSize = 0.0; + + + // check to see if zone is in the area type for the segment being calculated + boolean validSegment = false; + if ( segmentString.equalsIgnoreCase( TazDataHandler.AreaType.CBD.name() ) ) { + if ( tazDataManager.getZoneIsCbd( zoneNumber ) == 1 ) + validSegment = true; + } + else if ( segmentString.equalsIgnoreCase( TazDataHandler.AreaType.URBAN.name() ) ) { + if ( tazDataManager.getZoneIsUrban( zoneNumber ) == 1 ) + validSegment = true; + } + else if ( segmentString.equalsIgnoreCase( TazDataHandler.AreaType.SUBURBAN.name() ) ) { + if ( tazDataManager.getZoneIsSuburban( zoneNumber ) == 1 ) + validSegment = true; + } + else if ( segmentString.equalsIgnoreCase( TazDataHandler.AreaType.RURAL.name() ) ) { + if ( tazDataManager.getZoneIsRural( zoneNumber ) == 1 ) + validSegment = true; + } + + // if segment is an area type and zone is not in this area type, zone's size will be 0. + if ( validSegment ) { + + // loop through the variables + for(int l=0; l < dcSizeVariablesList.length; l++) { + + // compute the size term element. + // note that field names used in destination choice size coefficients file must + // also be found in zonal data file. + // tempVariableTable[l] is 0-based indexed + float coefficient = tempCoefficients[l]; + float zonalValue = tempVariableTable[l][k]; + totalZonalSize += coefficient * zonalValue; + + } // l - variables in size calculation + + int index = modelStructure.getDcSizeArrayCategoryIndexOffset( ModelStructure.AT_WORK_CATEGORY ); + + // dcSize[p] is 1-based indexed + double[] subzoneWalkPercentages = tazDataManager.getZonalWalkPercentagesForTaz( zoneNumber ); + for( int l=0; l < numSubZones; l++ ) + dcSize[index][zoneNumber][l] = totalZonalSize * subzoneWalkPercentages[l]; + + } + + } // k (zonal loop) + + } + else { + + // loop through the zones and sub-zones to compute the size terms + for( int k=0; k < numZones; k++ ) { + + int zoneNumber = k + 1; + double totalZonalSize = 0.0; + + // loop through the variables + for(int l=0; l < dcSizeVariablesList.length; l++) { + + // compute the size term element. + // note that field names used in destination choice size coefficients file must + // also be found in zonal data file. + // tempVariableTable[l] is 0-based indexed + float coefficient = tempCoefficients[l]; + float zonalValue = tempVariableTable[l][k]; + totalZonalSize += coefficient * zonalValue; + + } // l - variables in size calculation + + // dcSize[p] is 1-based indexed + double[] subzoneWalkPercentages = tazDataManager.getZonalWalkPercentagesForTaz( zoneNumber ); + for( int l=0; l < numSubZones; l++ ) + dcSize[p][zoneNumber][l] = totalZonalSize * subzoneWalkPercentages[l]; + + } // k (zonal loop) + + } + + + } // i (purpose loop) + + // write a file of calculated size values, before any balancing or adjustments + purposeIndexOffset = modelStructure.getDcSizeArrayCategoryIndexOffset(tourCategory); + end = purposeIndexOffset + modelStructure.getNumDcSizeArrayCategorySegments(tourCategory); + + if(ModelStructure.MANDATORY_CATEGORY == tourCategory & dcSizeTermOutputFileName!=null) { + writeZonalDcSizeValues( dcSizeArrayPurposes, purposeIndexOffset, end ); + } + + } + + private void writeZonalDcSizeValues( String[] dcSizePurposeList, int start, int end ) { + + try { + + // create the writer + PrintWriter outStream = new PrintWriter(new BufferedWriter( new FileWriter(dcSizeTermOutputFileName) ) ); + + // make the header + String header = String.format("%s", "zone,subzone" ); + + // loop through the purpose and segment lists to build the header + for( int i=0; i < dcSizePurposeList.length; i++ ) { + String purposeString = dcSizePurposeList[i]; + header += String.format(",%s",purposeString); + } // i + outStream.println(header); + + + // loop through the zones + for( int i=1; i <= numZones; i++ ) { + + int rowNumber = i; + int zoneNumber = (int) tazDataManager.getTazNumber( rowNumber ); + + // loop through sub zones + for( int j=0; j < numSubZones; j++ ) { + + String indexRecord = String.format("%d,%s", zoneNumber, subZoneNames[j]); + String dataRecord = ""; + + // print 0 for empty purposes + for( int k=0; k < start; k++ ) + dataRecord += String.format(",%.5f",0.0); + + // loop through the purposes and segments within purposes and print the size terms + for( int k=start; k < end; k++ ) + dataRecord += String.format(",%.5f",dcSize[k][zoneNumber][j]); + + // print 0 for empty purposes + for( int k=end; k < dcSizePurposeList.length; k++ ) + dataRecord += String.format(",%.5f",0.0); + + // write the line + outStream.println(indexRecord+dataRecord); + + } // j (sub zone loop) + + } // i (zone loop) + + outStream.close(); + + } + catch (IOException e) { + logger.fatal("IO Exception writing calcualted DC Size values to file: " + dcSizeTermOutputFileName ); + throw new RuntimeException(e); + } + + } + + + + + /** + * Scale the destination choice size values so that the total modeled destinations by purpose and segment match the total origins. + * total Origin/Destination constraining usuallu done for home oriented mandatory tours, e.g. work university, school. + * This method also has the capability to read a file of destination size adjustments and apply them during the balancing procedure. + * This capability was used in the Morpc model and was transferred to the Baylanta project, but may or may not be used. + * + * @param originsByHomeZone - total long term choice origin locations (i.e. number of workers, university students, or school age students) + * in residence zone, subzone, by purpose, segment. + * + */ + public void balanceSizeVariables( int[][][] originsByHomeZone, String[] purposeList, int start, int end ) { + + // store the original size variable values determined when ZonalDataManager object was created. + // set the initial sizeBalance values to the original size variable values. + + originalSize = duplicateDouble3DArray ( dcSize, start, end ); + balanceSize = duplicateDouble3DArray ( dcSize, start, end ); + + // create the shadow price array + shadowPrice = new double[purposeList.length][][]; + + // create the total origin locations array + double[] totalOriginLocations = new double[purposeList.length]; + + // store the dc size terms with no overrides + double[] totalDcSizeNoOverrides = new double[purposeList.length]; + + // store the dc size terms with overrides + double[] totalDcSizeWithOverrides = new double[purposeList.length]; + + for(int i=0;i 0.0) + scaledSize[i][k][l] = ( balanceSize[dcSizeArrayIndex][k][l] * totalOriginLocations[i] ) / totalDcSizeNoOverrides[i]; + else + scaledSize[i][k][l] = 0.0f; + } + + tot += scaledSize[i][k][l]; + + } + } + } + + //TODO: create a new class for destination choice size adjustments and define input file format + /** + * + * I probably want to make the destination choice size adjustments procedure a separate class and create a method + * that will produce the following log report that can be called from here. + * + * + if ( adjustmentSet.size() > 0 ) { + + // log out final adjusted and scaled size values for subzones affected by specified adjustments + logger.info( "" ); + logger.info( "Size variables for subzones with adjustments specified, after adjustments, after scaling" ); + String logString = String.format("%13s %13s", "Zone", "Subzone" ); + for ( int i=1; i < Structure.WorkDcSegments.values().length; i++ ) + logString += String.format(" %13s", Structure.WorkDcSegments.values()[i].name() ); + logger.info( logString ); + boolean[][] subzoneLogged = new boolean[numZones+1][numSubZones]; + Iterator it = adjustmentSet.iterator(); + while ( it.hasNext() ) { + Adjustment adj = (Adjustment)it.next(); + for (int w=0; w < numSubZones; w++) { + if ( subzoneLogged[adj.zone][w] == false ) { + logString = String.format("%13d %13d", adj.zone, w ); + for ( int k=1; k < Structure.WorkDcSegments.values().length; k++ ) + logString += String.format(" %13.2f", scaledSize[k][adj.zone][w] ); + logger.info( logString ); + + subzoneLogged[adj.zone][w] = true; + } + } + } + + } + */ + + + + + // set destination choice size variables for the first iteration of shadow pricing to calculated scaled values, + // one purpose at a time, for purposes that will have shadow pricing adjustments. + // non-mandatory type size values aren't scaled (not total origin/destination constrained). + + //TODO: make a method in StructureTourpose to return only purposes for which shadow pricing is applied. + // for now, all purposes have shadow pricing + for(int i=0;i 0 ) { + + // log a report of total destination choice size calculated by puprpose, segment - start by logging a header for the report, + // then print lines of values of the adjustments + logger.info(""); + logger.info( "Size Variable Adjustments Specified" ); + String logString = String.format("%13s %13s %13s %13s", "Purpose", "Segment", "Zone", "Code" ); + for ( Structure.TourPurpose purpose : Structure.TourPurpose.values() ) { + Structure.Segment[] segments = purpose.getSegments(); + for ( int s=0; s < segments.length; s++ ) + logString += String.format(" %13s", segments[s].getName() ); + logger.info( logString ); + + Iterator it = adjustmentSet.iterator(); + while ( it.hasNext() ) { + Adjustment adj = (Adjustment)it.next(); + + logString = String.format("%-13s %13d %13s ", purpose.name(), adj.zone, adj.code); + for (int i=0; i < adj.adjustment.length; i++) + logString += String.format(" %13.2f", adj.adjustment[i] ); + logger.info( logString ); + + } + + } + + + + // log out original size values for subzones affected by specified adjustments + logger.info( "" ); + logger.info( "Size variables for subzones with adjustments specified, before adjustments, before scaling" ); + logString = String.format("%13s %13s", "Zone", "Subzone" ); + for ( int i=1; i < Structure.WorkDcSegments.values().length; i++ ) + logString += String.format(" %13s", Structure.WorkDcSegments.values()[i].name() ); + logger.info( logString ); + boolean[][] subzoneLogged = new boolean[numZones+1][numSubZones]; + it = adjustmentSet.iterator(); + while ( it.hasNext() ) { + Adjustment adj = (Adjustment)it.next(); + for (int w=0; w < numSubZones; w++) { + if ( subzoneLogged[adj.zone][w] == false ) { + logString = String.format("%13d %13d", adj.zone, w ); + for ( int k=1; k < Structure.WorkDcSegments.values().length; k++ ) + logString += String.format(" %13.2f", originalSize[k][adj.zone][w] ); + logger.info( logString ); + + subzoneLogged[adj.zone][w] = true; + } + } + } + + + + subzoneOverRides = new boolean[Structure.WorkDcSegments.values().length][numZones+1][numSubZones]; + + // apply adjustments + it = adjustmentSet.iterator(); + while ( it.hasNext() ) { + Adjustment adj = (Adjustment)it.next(); + applySizeVariableAdjustments( adj, originsByHomeZone, totalDcSizeNoOverrides, totalDcSizeWithOverrides ); + + if ( adj.code.equalsIgnoreCase("O") ) { + for (int w = 0; w < numSubZones; w++) { + for (int p=0; p < adj.adjustment.length; p++) { + if ( adj.adjustment[p] != 0.0 ) { + subzoneOverRides[p+1][adj.zone][w] = true; + } + } + } + } + + } + + + // log out adjusted, but un-scaled size values for subzones affected by specified adjustments + logger.info( "" ); + logger.info( "Size variables for subzones with adjustments specified, after adjustments, before scaling" ); + logString = String.format("%13s %13s", "Zone", "Subzone" ); + for ( int i=1; i < Structure.WorkDcSegments.values().length; i++ ) + logString += String.format(" %13s", Structure.WorkDcSegments.values()[i].name() ); + logger.info( logString ); + Arrays.fill(subzoneLogged, false); + it = adjustmentSet.iterator(); + while ( it.hasNext() ) { + Adjustment adj = (Adjustment)it.next(); + for (int w=0; w < numSubZones; w++) { + if ( subzoneLogged[adj.zone][w] == false ) { + logString = String.format("%13d %13d", adj.zone, w ); + for ( int k=1; k < Structure.WorkDcSegments.values().length; k++ ) + logString += String.format(" %13.2f", balanceSize[k][adj.zone][w] ); + logger.info( logString ); + + subzoneLogged[adj.zone][w] = true; + } + } + } + + + + } + + **************/ + + + return subzoneOverRides; + + } + + + private ArrayList getDestinationChoiceSizeAdjustments() { + + /* define a set of adjustments to make, for testing purposes + + // create an Adjustment object for a zone - (multiply, add, overRide, zone) + // for a worker with segments - (LO, MED, HI, VHI, PT). + // These are read in from a file in production runs. + + // put adjustment objects in an ArrayList to return + ArrayList adjustmentSet = new ArrayList(); + + double[] testAdj1 = { 0.0, 2.0, 0.0, 0.0, 0.0 }; + double[] testAdj2 = { 0.0, 75.0, 0.0, 0.0, 50.0 }; + double[] testAdj3 = { 0.0, 0.0, 0.0, 1100.0, 0.0 }; + + adjustmentSet.add( new Adjustment( 800, "M", testAdj1 ) ); + adjustmentSet.add( new Adjustment( 800, "A", testAdj2 ) ); + adjustmentSet.add( new Adjustment( 300, "O", testAdj3 ) ); + + end of code to define testing adjustments */ + + + ArrayList adjustmentSet = readAdjustmentsFile(); + return adjustmentSet; + + } + + + private ArrayList readAdjustmentsFile () { + + if(destChoiceWorkerAdjustmentFileName.equalsIgnoreCase("Not yet implemented")) + return new ArrayList(); + + // put adjustment objects in an ArrayList to return + ArrayList adjustmentSet = new ArrayList(); + TableDataSet table = null; + + try { + CSVFileReader reader = new CSVFileReader(); + table = reader.readFile(new File(destChoiceWorkerAdjustmentFileName)); + } + catch (IOException e) { + logger.error ( "exception thrown reading destination choice adjustments file: " + destChoiceWorkerAdjustmentFileName, e ); + } + + for (int row=1; row <= table.getRowCount(); row++) { + String[] rowStringValues = table.getRowValuesAsString(row); + + int zone = Integer.parseInt(rowStringValues[0]); + String code = rowStringValues[1].toUpperCase(); + + double[] values = new double[rowStringValues.length-2]; + for (int j=2; j < rowStringValues.length; j++) + values[j-2] = Double.parseDouble(rowStringValues[j]); + + adjustmentSet.add( new Adjustment( zone, code, values ) ); + + } + + return adjustmentSet; + } + + + + private void applySizeVariableAdjustments( Adjustment adj, double[][][] originsByHomeZone, double[] totalDcSizeNoOverrides, double[] totalDcSizeWithOverrides ) { + + //TODO: need to implement this in new class for destination choice adjustments + /** + * + + // make adjustments as specified + for (int w = 0; w < numSubZones; w++) { + + for ( int p=0; p < adj.adjustment.length; p++ ) { + + // it is assumed that only non-zero adjustment values will be indications of an adjustment to be made + if ( adj.adjustment[p] == 0.0 ) + continue; + + double origValue = balanceSize[p+1][adj.zone][w]; + double adjValue = origValue; + + + // apply adjustments and save adjusted size value for the specific purpose. + // scaling for zones with O adjustments will be based on total Ps and As without the over-rides. + // scaling for zones with M or A adjustments will be based on Ps and As that include those adjustments + + // if over-ride value, ignore any multiply and/or add values also specified: + if ( adj.code.equalsIgnoreCase("O") ) { + + // get over-ride value for this subzone + adjValue = zonalWalkPctArray[w][adj.zone]*adj.adjustment[p]; + + originsByHomeZone[p+1][adj.zone][w] -= adjValue; + totalDcSizeNoOverrides[p+1] -= origValue; + totalDcSizeWithOverrides[p+1] += ( adjValue - origValue ); + + } + else { + // otherwise, apply multiply and/or add: + + if ( adj.code.equalsIgnoreCase("M") ) + adjValue *= adj.adjustment[p]; + if ( adj.code.equalsIgnoreCase("A") ) + adjValue += zonalWalkPctArray[w][adj.zone]*adj.adjustment[p]; + + // adjust destination choice size and origin location totals for mandatory types by the adjustment increment; don't need to adjust for non-mandatory as no scaling is done. + totalDcSizeNoOverrides[p+1] += ( adjValue - origValue ); + totalDcSizeWithOverrides[p+1] += ( adjValue - origValue ); + + } + + + + // apply adjusted values to size variable arrays for specific purpose + balanceSize[p+1][adj.zone][w] = adjValue; + + } + + } + + */ + + } + + + + + public int getDcSizeArrayPurposeIndex(String purposeString){ + int index = -1; + try { + if ( purposeString.indexOf('_') < 0 ) + purposeString = purposeString.toLowerCase() + "_" + purposeString.toLowerCase(); + index = modelStructure.getDcSizeArrayPurposeIndex( purposeString ); + } + catch ( Exception e ) { + logger.fatal("Purpose " + purposeString + " is not defined in Destination Choice Size Coefficients file.", e); + throw new RuntimeException(); + } + return index; + } + + + public double getDcSize( int index, int zone, int walkSubzone){ + return dcSize[index][zone][walkSubzone]; + } + + + public void updateSizeVariables(String[] tourPurposeList, int start, int end) { + + // only size variables for mandatory types are adjusted by shadow prices + + //TODO: make a method in StructureTourpose to return only purposes for which shadow pricing is applied. + // for now, all purposes have shadow pricing + for( int i=0; i < tourPurposeList.length; i++ ) { + String purposeString = tourPurposeList[i]; + int dcModelIndex = modelStructure.getDcModelPurposeIndex(purposeString); + int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex(dcModelIndex); + for(int k=1; k <= numZones; k++ ) { + for( int l=0; l < numSubZones; l++ ) { + dcSize[dcSizeArrayIndex][k][l] = scaledSize[i][k][l] * shadowPrice[i][k][l]; + if ( dcSize[dcSizeArrayIndex][k][l] < 0.0f ) + dcSize[dcSizeArrayIndex][k][l] = 0.0f; + } + } + } + + } + + + + public void updateShadowPrices( double[][][] modeledDestinationLocationsByDestZone, String[] tourPurposeList ) { + + // only size variables for mandatory types are adjusted by shadow prices + + //TODO: make a method in StructureTourpose to return only purposes for which shadow pricing is applied. + // for now, all purposes have shadow pricing + for( int i=0; i < tourPurposeList.length; i++) { +// String purposeString = tourPurposeList[i]; +// int dcModelIndex = modelStructure.getDcModelPurposeIndex(purposeString); +// int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex(dcModelIndex); + for( int k=1; k <=numZones; k++ ) { + for( int l=0; l < numSubZones; l++ ) { + if ( modeledDestinationLocationsByDestZone[i][k][l] > 0 ) + shadowPrice[i][k][l] *= ( scaledSize[i][k][l] / modeledDestinationLocationsByDestZone[i][k][l] ); + else + shadowPrice[i][k][l] *= scaledSize[i][k][l]; + } + } + } + } + + + + public void reportMaxDiff( int iteration, double[][][] modeledDestinationLocationsByDestZone, String[] tourPurposeList ) { + + + double[] maxSize = { 10, 100, 1000, Double.MAX_VALUE }; + double[] maxDeltas = { 0.05, 0.10, 0.25, 0.50, 1.0, Double.MAX_VALUE }; + + int[] nObs = new int[maxSize.length]; + double[] sse = new double[maxSize.length]; + double[] sumObs = new double[maxSize.length]; + + + logger.info( "Shadow Price Iteration " + iteration ); + + double minRange = 0.0; + for ( int r=0; r < maxSize.length; r++ ) { + + logger.info( String.format( "Frequency of chosen zone,subzone locations with non-zero DC Size < %s by range of relative error", (maxSize[r]<1000000 ? String.format("%.1f", maxSize[r]) : "+Inf") ) ); + logger.info( String.format( "%-24s %15s %15s %15s %15s %15s %15s %15s %8s", "purpose", "0 DCs", "< 5%", "< 10%", "< 25%", "< 50%", "< 100%", "100% +", "Total" ) ); + + int tot = 0; + int[] tots = new int[maxDeltas.length+1]; + String logRecord = ""; + for( int i=0; i < tourPurposeList.length; i++ ) { + + //String purposeString = tourPurposeList[i]; + //int dcModelIndex = modelStructure.getDcModelPurposeIndex(purposeString); + //int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex(dcModelIndex); + + tot = 0; + int[] freqs = new int[maxDeltas.length+1]; + int nonZeroSizeLocs = 0; + for( int k=1; k <= numZones; k++ ) { + for( int l=0; l < numSubZones; l++ ) { + + if ( scaledSize[i][k][l] > minRange && scaledSize[i][k][l] <= maxSize[r] ) { + + nonZeroSizeLocs++; + + if ( modeledDestinationLocationsByDestZone[i][k][l] == 0.0 ) { + // store the number of DC alternatives where DC Size > 0, but alternative was not chosen. + // relative error measure is not meaningful for this case, so report number of cases separately. + freqs[0] ++; + + // calculations for %RMSE + sse[r] += scaledSize[i][k][l]*scaledSize[i][k][l]; + } + else { + + double relDiff = Math.abs( scaledSize[i][k][l] - modeledDestinationLocationsByDestZone[i][k][l] ) / scaledSize[i][k][l]; + for ( int j=0; j < maxDeltas.length; j++ ) { + if ( relDiff < maxDeltas[j] ) { + // store number of DC alternatives chosen where DC Size > 0, by relative error range. + freqs[j+1]++; + break; + } + } + + // calculations for %RMSE + sse[r] += relDiff*relDiff; + } + + // calculations for %RMSE + sumObs[r] += scaledSize[i][k][l]; + nObs[r]++; + + } + } + } + + for ( int k=0; k < freqs.length; k++ ) { + tots[k] += freqs[k]; + tot += freqs[k]; + } + + logRecord = String.format( "%-24s", tourPurposeList[i] ); + + for ( int k=0; k < freqs.length; k++ ) { + float pct = 0.0f; + if ( tot > 0 ) + pct = (float)(100.0*freqs[k]/tot); + logRecord += String.format( " %6d (%5.1f%%)", freqs[k], pct ); + } + + logRecord += String.format( " %8d", tot ); + logger.info( logRecord ); + + } + + + tot = 0; + for ( int k=0; k < tots.length; k++ ) { + tot += tots[k]; + } + + logRecord = String.format( "%-24s", "Total" ); + String underline = String.format( "------------------------" ); + + for ( int k=0; k < tots.length; k++ ) { + float pct = 0.0f; + if ( tot > 0 ) + pct = (float)(100.0*tots[k]/tot); + logRecord += String.format( " %6d (%5.1f%%)", tots[k], pct ); + underline += String.format( "----------------" ); + } + + logRecord += String.format( " %8d", tot ); + underline += String.format( "---------" ); + + logger.info( underline ); + logger.info( logRecord ); + + + double rmse = -1.0; + if ( nObs[r] > 1 ) + rmse = 100.0 * ( Math.sqrt( sse[r]/(nObs[r] - 1) ) / ( sumObs[r]/nObs[r] ) ); + + logger.info( "%RMSE = " + ( rmse < 0 ? "N/A, no observations" : String.format("%.1f, with mean %.1f, for %d observations.", rmse, ( sumObs[r]/nObs[r] ), nObs[r]) ) ); + + logger.info( "" ); + + minRange = maxSize[r]; + + } + + logger.info( "" ); + logger.info( "" ); + + } + + + + public void updateShadowPricingInfo( int iteration, int[][][] originsByHomeZone, double[][][] modeledDestinationLocationsByDestZone, String[] tourPurposeList, int start, int end ) { + + + ArrayList tableHeadings = new ArrayList(); + tableHeadings.add("alt"); + tableHeadings.add("zone"); + tableHeadings.add("subzone"); + + + for( int i=0; i < tourPurposeList.length; i++ ){ + String purposeString = tourPurposeList[i]; + tableHeadings.add( String.format("%s_origins", purposeString) ); + tableHeadings.add( String.format("%s_sizeOriginal", purposeString) ); + tableHeadings.add( String.format("%s_sizeAdjOriginal", purposeString) ); + tableHeadings.add( String.format("%s_sizeScaled", purposeString) ); + tableHeadings.add( String.format("%s_sizePrevious", purposeString) ); + tableHeadings.add( String.format("%s_modeledDests", purposeString) ); + tableHeadings.add( String.format("%s_sizeFinal", purposeString) ); + tableHeadings.add( String.format("%s_shadowPrices", purposeString) ); + } + + // define a TableDataSet for use in writing output file + float[][] tableData = new float[numZones*numSubZones+1][tableHeadings.size()]; + + int alt = 1; + for ( int i=1; i <= numZones; i++ ) { + for ( int j=0; j < numSubZones; j++ ) { + + tableData[alt][0] = alt; + tableData[alt][1] = i; + tableData[alt][2] = j; + + int index = 3; + + for( int p=0; p < tourPurposeList.length; p++ ){ + String purposeString = tourPurposeList[p]; + int dcModelIndex = modelStructure.getDcModelPurposeIndex(purposeString); + int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex(dcModelIndex); + + tableData[alt][index++] = (float)originsByHomeZone[p][i][j]; + tableData[alt][index++] = (float)originalSize[dcSizeArrayIndex][i][j]; + tableData[alt][index++] = (float)originalAdjSize[dcSizeArrayIndex][i][j]; + tableData[alt][index++] = (float)scaledSize[p][i][j]; + tableData[alt][index++] = (float)previousSize[p][i][j]; + tableData[alt][index++] = (float)modeledDestinationLocationsByDestZone[p][i][j]; + tableData[alt][index++] = (float)dcSize[dcSizeArrayIndex][i][j]; + tableData[alt][index++] = (float)shadowPrice[p][i][j]; + } + alt++; + + } + + } + + TableDataSet outputTable = TableDataSet.create(tableData, tableHeadings); + + // write outputTable to new output file + try { + String newFilename = this.dcShadowOutputFileName.replaceFirst(".csv", "_" + iteration + ".csv"); + CSVFileWriter writer = new CSVFileWriter(); + writer.writeFile(outputTable, new File(newFilename), new DecimalFormat("#.000000000000")); + //writer.writeFile( outputTable, new File(newFilename) ); + } + catch (IOException e) { + throw new RuntimeException(e); + } + + + // save scaled size variables used in shadow price adjustmnents for reporting to output file + for(int i=0;i + * Started: Apr 14, 2009 11:09:58 AM + */ +public class FreeParkingChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(FreeParkingChoiceDMU.class); + + protected HashMap methodIndexMap; + + protected HouseholdIf hh; + protected PersonIf person; + private IndexValues dmuIndex; + + + public FreeParkingChoiceDMU() { + dmuIndex = new IndexValues(); + } + + /** need to set hh and home taz before using**/ + public void setPersonObject (PersonIf personObject) { + person = personObject; + hh = personObject.getHouseholdObject(); + } + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug Free Parking UEC" ); + } + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + /*dmu @ functions*/ + + public int getAutoOwnership() { + return hh.getAutoOwnershipModelResult(); + } + + public int getFtwkPersons() { + return hh.getNumFtWorkers(); + } + + public int getPtwkPersons() { + return hh.getNumPtWorkers(); + } + + public int getSize() { + return hh.getSize(); + } + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + public int getWorkLocation() { + return person.getUsualWorkLocation(); + } + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/HouseholdDataManager.java b/src/java/com/pb/models/ctrampIf/HouseholdDataManager.java new file mode 100644 index 0000000..d06e736 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/HouseholdDataManager.java @@ -0,0 +1,2271 @@ +package com.pb.models.ctrampIf; + +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.OLD_CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.util.IndexSort; +import com.pb.common.util.ObjectUtil; +import com.pb.common.util.SeededRandom; +import com.pb.common.model.ChoiceModelApplication; +import com.pb.common.model.LogitModel; +import com.pb.common.model.ConcreteAlternative; +import com.pb.models.ctrampIf.jppf.CtrampApplication; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.StringTokenizer; +import java.util.Random; + +import umontreal.iro.lecuyer.probdist.LognormalDist; +import umontreal.iro.lecuyer.probdist.NormalDist; + +import org.apache.log4j.Logger; + +/** + * @author Jim Hicks + * + * Class for managing household and person object data read from synthetic population files. + */ +public abstract class HouseholdDataManager implements HouseholdDataManagerIf, Serializable { + + protected transient Logger logger = Logger.getLogger(HouseholdDataManager.class); + + protected static int MAX_HHS_PER_FILE = 100000; + protected static int MAX_BYTES_HH_OBJECT = 30000; + protected static int NUMBER_OF_IN_MEMORY_HHS = 10000; + + + public static final String PROPERTIES_SYNPOP_INPUT_HH = "PopulationSynthesizer.InputToCTRAMP.HouseholdFile"; + public static final String PROPERTIES_SYNPOP_INPUT_HH_FIELD_NAME = "PopulationSynthesizer.InputToCTRAMP.HouseholdFile.Zone.Field.Name"; + public static final String PROPERTIES_SYNPOP_INPUT_PERS = "PopulationSynthesizer.InputToCTRAMP.PersonFile"; + public static final String PROPERTIES_WORK_OCCUPATION_CODES = "PopulationSynthesizer.InputToCTRAMP.WorkOccupationCodesFile"; + + public static final String PROPERTIES_WORK_OCCUPATION_INDCEN_MIN_FIELD_NAME = "IndCenMin"; + public static final String PROPERTIES_WORK_OCCUPATION_INDCEN_MAX_FIELD_NAME = "IndCenMax"; + public static final String PROPERTIES_WORK_OCCUPATION_INDCEN_WORKOCC_FIELD_NAME = "workerOccupation"; + + + public static final String RANDOM_SEED_NAME = "Model.Random.Seed"; + + public static final String HH_ID_FIELD_NAME = "HHID"; + public String HH_HOME_TAZ_FIELD_NAME = "TAZ"; + public static final String HH_INCOME_CATEGORY_FIELD_NAME = "hinccat1"; + public static final String HH_INCOME_DOLLARS_FIELD_NAME = "HINC"; + public static final String HH_WORKERS_FIELD_NAME = "hworkers"; + public static final String HH_AUTOS_FIELD_NAME = "VEHICL"; + public static final String HH_SIZE_FIELD_NAME = "PERSONS"; + public static final String HH_TYPE_FIELD_NAME = "HHT"; + public static final String HH_BLDGSZ_FIELD_NAME = "BLDGSZ"; + + public String[] hhHeadings = { + HH_ID_FIELD_NAME, + HH_HOME_TAZ_FIELD_NAME, + HH_INCOME_CATEGORY_FIELD_NAME, + HH_INCOME_DOLLARS_FIELD_NAME, + HH_WORKERS_FIELD_NAME, + HH_AUTOS_FIELD_NAME, + HH_SIZE_FIELD_NAME, + HH_TYPE_FIELD_NAME + }; + + + + public static final String PERSON_HH_ID_FIELD_NAME = "HHID"; + public static final String PERSON_PERSON_ID_FIELD_NAME = "PERID"; + public static final String PERSON_AGE_FIELD_NAME = "AGE"; + public static final String PERSON_GENDER_FIELD_NAME = "SEX"; + public static final String PERSON_EMPLOYMENT_CATEGORY_FIELD_NAME = "pemploy"; + public static final String PERSON_STUDENT_CATEGORY_FIELD_NAME = "pstudent"; + public static final String PERSON_TYPE_CATEGORY_FIELD_NAME = "ptype"; + public static final String PERSON_EDUC_CATEGORY_FIELD_NAME = "EDUC"; + public static final String PERSON_INDCEN_CATEGORY_FIELD_NAME = "INDCEN"; + + public static final String[] persHeadings = { + PERSON_HH_ID_FIELD_NAME, + PERSON_PERSON_ID_FIELD_NAME, + PERSON_AGE_FIELD_NAME, + PERSON_GENDER_FIELD_NAME, + PERSON_EMPLOYMENT_CATEGORY_FIELD_NAME, + PERSON_STUDENT_CATEGORY_FIELD_NAME, + PERSON_TYPE_CATEGORY_FIELD_NAME, + PERSON_EDUC_CATEGORY_FIELD_NAME, + PERSON_INDCEN_CATEGORY_FIELD_NAME + }; + + + public static final String PROPERTIES_HOUSEHOLD_TRACE_LIST = "Debug.Trace.HouseholdIdList"; + + + private static final String PROPERTIES_MIN_VALUE_OF_TIME_KEY = "HouseholdManager.MinValueOfTime"; + private static final String PROPERTIES_MAX_VALUE_OF_TIME_KEY = "HouseholdManager.MaxValueOfTime"; + private static final String PROPERTIES_MEAN_VALUE_OF_TIME_VALUES_KEY = "HouseholdManager.MeanValueOfTime.Values"; + private static final String PROPERTIES_MEAN_VALUE_OF_TIME_INCOME_LIMITS_KEY = "HouseholdManager.MeanValueOfTime.Income.Limits"; + private static final String PROPERTIES_HH_VALUE_OF_TIME_MULTIPLIER_FOR_UNDER_18_KEY = "HouseholdManager.HH.ValueOfTime.Multiplier.Under18"; + private static final String PROPERTIES_MEAN_VALUE_OF_TIME_MULTIPLIER_FOR_MU_KEY = "HouseholdManager.Mean.ValueOfTime.Multiplier.Mu"; + private static final String PROPERTIES_VALUE_OF_TIME_LOGNORMAL_SIGMA_KEY = "HouseholdManager.ValueOfTime.Lognormal.Sigma"; + + protected float hhValueOfTimeMultiplierForPersonUnder18; + protected double meanValueOfTimeMultiplierBeforeLogForMu; + protected double valueOfTimeLognormalSigma; + + protected float minValueOfTime; + protected float maxValueOfTime; + protected float[] meanValueOfTime; + protected int[] incomeDollarLimitsForValueOfTime; // upper limits of income ranges; 0-based; length of array gives the number of income segments; + protected LognormalDist[] valueOfTimeDistribution; + + + protected HashMap propertyMap; + + protected String projectDirectory; + protected String outputHouseholdFileName; + protected String outputPersonFileName; + + protected TazDataIf tazDataManager; + protected ModelStructure modelStructure; + + protected TableDataSet hhTable; + protected TableDataSet personTable; + + protected HashSet householdTraceSet; + + protected HouseholdIf[] fullHhArray; + protected int[] hhIndexArray; + protected int numberOfHouseholds; + + protected int inputRandomSeed; + protected int numPeriods; + protected int firstPeriod; + + + protected float sampleRate; + protected int sampleSeed; + + private TableDataSet workerOccupationCodes; + + + + public HouseholdDataManager() { + } + + + + /** + * Associate data in hh and person TableDataSets read from synthetic population files with + * Household objects and Person objects with Households. + */ + protected abstract void mapTablesToHouseholdObjects(); + + + + public String testRemote() { + System.out.println("testRemote() called by remote process."); + return String.format("testRemote() method in %s called.", this.getClass().getCanonicalName() ); + } + + + public void setDebugHhIdsFromHashmap () { + + householdTraceSet = new HashSet(); + + // get the household ids for which debug info is required + String householdTraceStringList = propertyMap.get( PROPERTIES_HOUSEHOLD_TRACE_LIST ); + + if ( householdTraceStringList != null ) { + StringTokenizer householdTokenizer = new StringTokenizer(householdTraceStringList,","); + while(householdTokenizer.hasMoreTokens()){ + String listValue = householdTokenizer.nextToken(); + int idValue = Integer.parseInt( listValue.trim() ); + householdTraceSet.add( idValue ); + } + } + + logger.info("Household Trace Set: " + householdTraceSet); + } + + + + public void setupHouseholdDataManager( ModelStructure modelStructure, TazDataIf tazDataManager, String inputHouseholdFileName, String inputPersonFileName ) { + + this.tazDataManager = tazDataManager; + this.modelStructure = modelStructure; + + //get HH zone field name + HH_HOME_TAZ_FIELD_NAME = propertyMap.get(PROPERTIES_SYNPOP_INPUT_HH_FIELD_NAME ); + + // read synthetic population files + readHouseholdData(inputHouseholdFileName); + readPersonData(inputPersonFileName); + + // Set the seed for the JVM default SeededRandom object - should only be used to set the order for the + // HH index array so that hhs can be processed in an arbitrary order as opposed to the order imposed by + // the synthetic population generator. + // The seed was set as a command line argument for the model run, or the default if no argument supplied + SeededRandom.setSeed( sampleSeed ); + + // the seed read from the properties file controls seeding the Household object random number generator objects. + inputRandomSeed = Integer.parseInt( propertyMap.get( HouseholdDataManager.RANDOM_SEED_NAME ) ); + + // map synthetic population table data to objects to be used by CT-RAMP + mapTablesToHouseholdObjects(); + hhTable = null; + personTable = null; + + numberOfHouseholds = fullHhArray.length; + logPersonSummary( fullHhArray ); + + setTraceHouseholdSet(); + + } + + + + + public void setPropertyFileValues ( HashMap propertyMap ) { + + String propertyValue = ""; + this.propertyMap = propertyMap; + + // save the project specific parameters in class attributes + this.projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + setDebugHhIdsFromHashmap (); + + propertyValue = propertyMap.get( CtrampApplication.PROPERTIES_SCHEDULING_NUMBER_OF_TIME_PERIODS ); + if ( propertyValue == null ) + numPeriods = 0; + else + numPeriods = Integer.parseInt( propertyValue ); + + propertyValue = propertyMap.get( CtrampApplication.PROPERTIES_SCHEDULING_FIRST_TIME_PERIOD ); + if ( propertyValue == null ) + firstPeriod = 0; + else + firstPeriod = Integer.parseInt( propertyValue ); + + } + + + public int[] getRandomOrderHhIndexArray( int numHhs ) { + + int[] data = new int[numHhs]; + for ( int i=0; i < numHhs; i++ ) + data[i] = (int)(100000000*SeededRandom.getRandom()); + + return IndexSort.indexSort( data ); + + } + + + public int[] getHomeTazOrderHhIndexArray( int[] hhSortArray ) { + return IndexSort.indexSort( hhSortArray ); + } + + + private void resetRandom(HouseholdIf h, int count) { + // get the household's Random + Random r = h.getHhRandom(); + + int seed = inputRandomSeed + h.getHhId(); + r.setSeed( seed ); + + // select count Random draws to reset this household's Random to it's state prior to + // the model run for which model results were stored in HouseholdDataManager. + for ( int i=0; i < count; i++ ) + r.nextDouble(); + + // reset the randomCount for the household's Random + h.setHhRandomCount(count); + } + + + public void resetUwslRandom( int iter ) { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current random count for the end of the shadow price iteration passed in. + // this value was set at the end of UsualWorkSchoolLocation model step for the given iter. + // if < 0, random count should be set to 0. + int uwslCount = 0; + if ( iter >= 0 ) { + uwslCount = tempHhs[r].getUwslRandomCount( iter ); + } + + // draw uwslCount random numbers from the household's Random + resetRandom(tempHhs[r], uwslCount); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetAoRandom( int iter ) { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int aoCount = tempHhs[r].getUwslRandomCount( iter ); + + // draw stlCount random numbers + resetRandom( tempHhs[r], aoCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetFpRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int fpCount = tempHhs[r].getAoRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], fpCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetCdapRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int cdapCount = tempHhs[r].getFpRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], cdapCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetImtfRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int imtfCount = tempHhs[r].getCdapRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], imtfCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetImtodRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int imtodCount = tempHhs[r].getImtfRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], imtodCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetImmcRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to mode choice model from the Household object. + // this value was set at the end of time of day step. + int immcCount = tempHhs[r].getImtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], immcCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetJtfRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int jtfCount = tempHhs[r].getImtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], jtfCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetJtlRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int jtlCount = tempHhs[r].getJtfRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], jtlCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetJtodRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int jtodCount = tempHhs[r].getJtlRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], jtodCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + public void resetJmcRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to mode choice model from the Household object. + // this value was set at the end of time of day step. + int jmcCount = tempHhs[r].getJtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], jmcCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + public void resetInmtfRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int inmtfCount = tempHhs[r].getJtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], inmtfCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetInmtlRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int inmtlCount = tempHhs[r].getInmtfRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], inmtlCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetInmtodRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int inmtodCount = tempHhs[r].getInmtlRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], inmtodCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetInmmcRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to mode choice model from the Household object. + // this value was set at the end of time of day step. + int inmmcCount = tempHhs[r].getInmtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], inmmcCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetAwfRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int awfCount = tempHhs[r].getInmtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], awfCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetAwlRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int awlCount = tempHhs[r].getAwfRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], awlCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetAwtodRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int awtodCount = tempHhs[r].getAwlRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], awtodCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetAwmcRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to mode choice model from the Household object. + // this value was set at the end of time of day step. + int awmcCount = tempHhs[r].getAwtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], awmcCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + public void resetStfRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int stfCount = tempHhs[r].getAwtodRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], stfCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + public void resetStlRandom() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) { + // get the current count prior to stop location model from the Household object. + // this value was set at the end of stop frequency model step. + int stlCount = tempHhs[r].getStfRandomCount(); + + // draw stlCount random numbers + resetRandom( tempHhs[r], stlCount ); + } + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of UsualWorkSchoolLocation model step. + public void setUwslRandomCount( int iter ) { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setUwslRandomCount( iter, tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Auto Ownership model step. + public void setAoRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setAoRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Auto Ownership model step. + public void setFpRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setFpRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Coordinated Daily Activity Pattern model step. + public void setCdapRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setCdapRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Individual Mandatory Tour Frequency model step. + public void setImtfRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setImtfRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Individual Mandatory Tour Departure and Duration model step. + public void setImtodRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setImtodRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of At-work Subtour Frequency model step. + public void setAwfRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setAwfRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of At-work Subtour Location Choice model step. + public void setAwlRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setAwlRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of At-work Subtour Departure time, duration and mode choice model step. + public void setAwtodRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setAwtodRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Joint Tour Frequency model step. + public void setJtfRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setJtfRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + // this is called at the end of Joint Tour Destination Choice model step. + public void setJtlRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setJtlRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Joint Tour departure and duration Choice model step. + public void setJtodRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setJtodRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Individual non-mandatory Tour frequency Choice model step. + public void setInmtfRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setInmtfRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Individual non-mandatory Tour destination choice Choice model step. + public void setInmtlRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setInmtlRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Individual non-mandatory Tour departure and duration choice Choice model step. + public void setInmtodRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setInmtodRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Stop Frequency Choice model step. + public void setStfRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setStfRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + // this is called at the end of Stop Location Choice model step. + public void setStlRandomCount() { + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setStlRandomCount( tempHhs[r].getHhRandomCount() ); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + } + + + + /** + * set the hh id for which debugging info from choice models applied to this household will be logged if debug logging. + */ + public void setDebugHouseholdId( int debugHhId, boolean value ) { + int index = hhIndexArray[debugHhId]; + HouseholdIf tempHh = getHhArrayElement( index ); + tempHh.setDebugChoiceModels(value); + setHhArrayElement( tempHh, index ); + } + + + /** + * Sets the HashSet used to trace households for debug purposes and sets the + * debug switch for each of the listed households. Also sets + */ + public void setTraceHouseholdSet() { + + // loop through the households in the set and set the trace switches + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + for ( int r=0; r < tempHhs.length; r++ ) + tempHhs[r].setDebugChoiceModels(false); + setHhArray( tempHhs, startRange ); + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + + for( int id : householdTraceSet ) { + int index = hhIndexArray[id]; + HouseholdIf tempHh = getHhArrayElement( index ); + tempHh.setDebugChoiceModels(true); + setHhArrayElement( tempHh, index ); + } + + } + + + + /** + * Sets the sample rate used to run the model for a portion of the households. + * @param sampleRate, proportion of total households for which to run the model [0.0, 1.0]. + */ + public void setHouseholdSampleRate( float sampleRate, int sampleSeed ) { + this.sampleRate = sampleRate; + this.sampleSeed = sampleSeed; + } + + + + public void setHhArray(HouseholdIf[] hhArray) { + fullHhArray = hhArray; + } + + + public void setHhArray( HouseholdIf[] tempHhs, int startIndex ) { + for (int i=0; i < tempHhs.length; i++) { + fullHhArray[startIndex + i] = tempHhs[i]; + } + } + + public void setHhArrayElement( HouseholdIf tempHh, int index ) { + fullHhArray[index] = tempHh; + } + + + /** + * return the array of Household objects holding the synthetic population and choice model outcomes. + * @return hhs + */ + public HouseholdIf[] getHhArray() { + return fullHhArray; + } + + + public HouseholdIf[] getHhArray(int first, int last) { + HouseholdIf[] tempHhs = null; + tempHhs = new HouseholdIf[last-first+1]; + + for (int i=0; i < tempHhs.length; i++) { + tempHhs[i] = fullHhArray[first + i]; + } + + return tempHhs; + } + + + public HouseholdIf getHhArrayElement( int index ) { + return fullHhArray[index]; + } + + + public int getArrayIndex( int hhId ){ + int i = hhIndexArray[hhId]; + return i; + } + + /** + * return the number of household objects read from the synthetic population. + * @return + */ + public int getNumHouseholds() { + return numberOfHouseholds; + } + + + + /** + * set walk segment (0-none, 1-short, 2-long walk to transit access) for the origin for this tour + */ + public short getInitialOriginWalkSegment (short taz, double randomNumber) { + double[] proportions = tazDataManager.getZonalWalkPercentagesForTaz( taz ); + return (short)ChoiceModelApplication.getMonteCarloSelection(proportions, randomNumber); + } + + + + + private void readHouseholdData( String inputHouseholdFileName ) { + + // construct input household file name from properties file values + String fileName = projectDirectory + "/" + inputHouseholdFileName; + + try{ + logger.info( "reading popsyn household data file." ); + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + reader.setDelimSet( "," + reader.getDelimSet() ); + hhTable = reader.readFile(new File( fileName )); + } + catch(Exception e){ + logger.fatal( String.format( "Exception occurred reading synthetic household data file: %s into TableDataSet object.", fileName ) ); + throw new RuntimeException(e); + } + + } + + + private void readPersonData( String inputPersonFileName ) { + + // construct input person file name from properties file values + String fileName = projectDirectory + "/" + inputPersonFileName; + + try{ + logger.info( "reading popsyn person data file." ); + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + reader.setDelimSet( "," + reader.getDelimSet() ); + personTable = reader.readFile(new File( fileName )); + } + catch(Exception e){ + logger.fatal( String.format( "Exception occurred reading synthetic person data file: %s into TableDataSet object.", fileName ) ); + throw new RuntimeException(e); + } + + } + + + + + public void logPersonSummary( HouseholdIf[] hhs ) { + + HashMap> summaryResults; + + summaryResults = new HashMap>(); + + for(int i=0; i < hhs.length; ++i){ + + HouseholdIf household = hhs[i]; + + PersonIf[] personArray = household.getPersons(); + for (int j = 1; j < personArray.length; ++j) { + PersonIf person = personArray[j]; + String personType = person.getPersonType(); + + String employmentStatus = person.getPersonEmploymentCategory(); + String studentStatus = person.getPersonStudentCategory(); + int age = person.getAge(); + int ageCategory; + if (age <= 5) { + ageCategory = 0; + } else if (age <= 15) { + ageCategory = 1; + } else if (age <= 18) { + ageCategory = 2; + } else if (age <= 24) { + ageCategory = 3; + } else if (age <= 44) { + ageCategory = 4; + } else if (age <= 64) { + ageCategory = 5; + } else { + ageCategory = 6; + } + + if (summaryResults.containsKey(personType)) { + //have person type + if (summaryResults.get(personType).containsKey(employmentStatus)) { + //have employment category + summaryResults.get(personType).get(employmentStatus)[ageCategory]+=1; + } else { + //don't have employment category + summaryResults.get(personType).put(employmentStatus, new int[7]); + summaryResults.get(personType).get(employmentStatus)[ageCategory]+=1; + } + if (summaryResults.get(personType).containsKey(studentStatus)) { + //have student category + summaryResults.get(personType).get(studentStatus)[ageCategory]+=1; + } else { + //don't have student category + summaryResults.get(personType).put(studentStatus, new int[7]); + summaryResults.get(personType).get(studentStatus)[ageCategory]+=1; + } + } else { + //don't have person type + summaryResults.put(personType, new HashMap()); + summaryResults.get(personType).put(studentStatus, new int[7]); + summaryResults.get(personType).get(studentStatus)[ageCategory]+=1; + summaryResults.get(personType).put(employmentStatus, new int[7]); + summaryResults.get(personType).get(employmentStatus)[ageCategory]+=1; + } + } + } + String headerRow = String.format("%5s\t", "Age\t"); + for (String empCategory: PersonIf.employmentCategoryNameArray) { + headerRow += String.format("%16s\t", empCategory ); + } + for (String stuCategory: PersonIf.studentCategoryNameArray) { + headerRow += String.format("%16s\t", stuCategory ); + } + String[] ageCategories = {"0-5","6-15","16-18","19-24","25-44","45-64","65+"}; + + for (String personType: summaryResults.keySet()) { + + logger.info("Summary for person type: " + personType); + + logger.info(headerRow); + String row = ""; + + HashMap personTypeSummary = summaryResults.get(personType); + + for (int j = 0; j getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + // hhs is dimesioned to number of households + 1. + int count=0; + for ( int r=0; r < tempHhs.length; r++ ) { + + PersonIf[] persons = tempHhs[r].getPersons(); + + int homeZone = tempHhs[r].getHhTaz(); + int homeSubZone = tempHhs[r].getHhWalkSubzone(); + + for ( int p=1; p < persons.length; p++) { + + PersonIf person = persons[p]; + + int purposeIndex = -1; + try { + + if ( person.getPersonIsWorker() == 1 ) { + + purposeIndex = person.getWorkLocationPurposeIndex(); + personsWithMandatoryPurpose[purposeIndex][homeZone][homeSubZone] ++; + + } + + if ( person.getPersonIsPreschoolChild() == 1 || person.getPersonIsStudentDriving() == 1 || person.getPersonIsStudentNonDriving() == 1 ) { + + purposeIndex = person.getSchoolLocationPurposeIndex(); + personsWithMandatoryPurpose[purposeIndex][homeZone][homeSubZone] ++; + + } + else if ( person.getPersonIsUniversityStudent() == 1 ) { + + purposeIndex = person.getUniversityLocationPurposeIndex(); + personsWithMandatoryPurpose[purposeIndex][homeZone][homeSubZone] ++; + + } + + count++; + + } + catch ( RuntimeException e ) { + logger.error ( String.format("exception caught summing workers/students by origin zone for household table record r=%d, startRange=%d, endRange=%d, count=%d.", r, startRange, endRange, count ) ); + throw e; + } + + } + + } // r (households) + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + return personsWithMandatoryPurpose; + + } + + + + + + public int[][] getIndividualNonMandatoryToursByHomeZoneSubZone( String purposeString ) { + + // dimension the array + int numZones = tazDataManager.getNumberOfZones(); + int numWalkSubzones = tazDataManager.getNumberOfSubZones(); + + int[][] individualNonMandatoryTours = new int[numZones+1][numWalkSubzones]; + + // hhs is dimesioned to number of households + 1. + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + // hhs is dimesioned to number of households + 1. + int count = 0; + for ( int r=0; r < tempHhs.length; r++ ) { + + + PersonIf[] persons = tempHhs[r].getPersons(); + + for ( int p=1; p < persons.length; p++) { + + PersonIf person = persons[p]; + + ArrayList it = person.getListOfIndividualNonMandatoryTours(); + + try { + + if ( it.size() == 0 ) + continue; + + for ( TourIf tour : it ) { + // increment the segment count if it's the right purpose + String tourPurpose = tour.getTourPrimaryPurpose(); + if ( purposeString.startsWith( tourPurpose ) ) { + int homeZone = tempHhs[r].getHhTaz(); + int homeSubZone = tempHhs[r].getHhWalkSubzone(); + individualNonMandatoryTours[homeZone][homeSubZone] ++; + count++; + } + } + + } + catch ( RuntimeException e ) { + logger.error ( String.format("exception caught counting number of individualNonMandatory tours for purpose: %s, for household table record r=%d, personNum=%d, startRange=%d, endRange=%d, count=%d.", purposeString, r, person.getPersonNum(), startRange, endRange, count ) ); + throw e; + } + + } + + } // r (households) + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + return individualNonMandatoryTours; + + } + + + + public double[][][] getMandatoryToursByDestZoneSubZone() { + + // dimension the array + int numZones = tazDataManager.getNumberOfZones(); + int numWalkSubzones = tazDataManager.getNumberOfSubZones(); + + // get correspondence between mandatory purpose names and their array indices + String[] mandatoryPurposes = modelStructure.getDcModelPurposeList( ModelStructure.MANDATORY_CATEGORY ); + HashMap tourPurposeIndexMap = new HashMap(); + for ( int p=0; p < mandatoryPurposes.length; p++ ) + tourPurposeIndexMap.put( mandatoryPurposes[p], p ); + + double[][][] mandatoryTours = new double[mandatoryPurposes.length][numZones+1][numWalkSubzones]; + + + + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + // hhs is dimesioned to number of households + 1. + int count = 0; + for ( int r=0; r < tempHhs.length; r++ ) { + + PersonIf[] persons = tempHhs[r].getPersons(); + + for ( int p=1; p < persons.length; p++) { + + PersonIf person = persons[p]; + + String purposeName = ""; + int purposeIndex = -1; + int destZone = -1; + int destSubZone = -1; + try { + + if ( person.getPersonIsWorker() == 1 && person.getPersonWorkLocationZone() > 0 ) { + + purposeIndex = person.getWorkLocationPurposeIndex(); + destZone = person.getPersonWorkLocationZone(); + destSubZone = person.getPersonWorkLocationSubZone(); + mandatoryTours[purposeIndex][destZone][destSubZone]++; + + } + + if ( person.getPersonIsPreschoolChild() == 1 || person.getPersonIsStudentDriving() == 1 || person.getPersonIsStudentNonDriving() == 1 && person.getPersonSchoolLocationZone() > 0 ) { + + purposeIndex = person.getSchoolLocationPurposeIndex(); + destZone = person.getPersonSchoolLocationZone(); + destSubZone = person.getPersonSchoolLocationSubZone(); + mandatoryTours[purposeIndex][destZone][destSubZone]++; + + } + else if ( person.getPersonIsUniversityStudent() == 1 && person.getPersonSchoolLocationZone() > 0 ) { + + purposeIndex = person.getUniversityLocationPurposeIndex(); + destZone = person.getPersonSchoolLocationZone(); + destSubZone = person.getPersonSchoolLocationSubZone(); + mandatoryTours[purposeIndex][destZone][destSubZone]++; + + } + + } + catch ( RuntimeException e ) { + logger.error ( String.format("exception caught counting number of mandatory tour destinations for purpose: %s, for household table record r=%d, personNum=%d.", purposeName, r, person.getPersonNum() ) ); + logger.error ( String.format(" r = %d.", r ) ); + logger.error ( String.format(" household id = %d.", tempHhs[r] ) ); + logger.error ( String.format(" personNum = %d.", person.getPersonNum() ) ); + logger.error ( String.format(" purpose name = %s, purposeIndex = %d.", purposeName, purposeIndex ) ); + logger.error ( String.format(" destZone = %d, destSubZone = %d.", destZone, destSubZone ) ); + logger.error ( String.format(" startRange = %d, endRange = %d, count = %d.", startRange, endRange, count ) ); + } + + } + + } // r (households) + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + return mandatoryTours; + + } + + + + public int[][] getJointToursByHomeZoneSubZone( String purposeString ) { + + // dimension the array + int numZones = tazDataManager.getNumberOfZones(); + int numWalkSubzones = tazDataManager.getNumberOfSubZones(); + + int[][] jointTours = new int[numZones+1][numWalkSubzones]; + + // hhs is dimesioned to number of households + 1. + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + // hhs is dimesioned to number of households + 1. + int count = 0; + for ( int r=0; r < tempHhs.length; r++ ) { + + try { + + TourIf[] jt = tempHhs[r].getJointTourArray(); + + if ( jt == null ) + continue; + + for ( int i=0; i < jt.length; i++ ) { + // increment the segment count if it's the right purpose + if ( jt[i].getTourPrimaryPurpose().equalsIgnoreCase( purposeString )) { + int homeZone = tempHhs[r].getHhTaz(); + int homeSubZone = tempHhs[r].getHhWalkSubzone(); + jointTours[homeZone][homeSubZone] ++; + count++; + } + } + + } + catch ( RuntimeException e ) { + logger.error ( String.format("exception caught counting number of joint tours for purpose: %s, for household table record r=%d, startRange=%d, endRange=%d, count=%d.", purposeString, r, startRange, endRange, count ) ); + throw e; + } + + } // r (households) + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + return jointTours; + } + + + public int[][] getAtWorkSubtoursByWorkZoneSubZone( String purposeString ) { + + // dimension the array + int numZones = tazDataManager.getNumberOfZones(); + int numWalkSubzones = tazDataManager.getNumberOfSubZones(); + + int[][] subtours = new int[numZones+1][numWalkSubzones]; + + // hhs is dimesioned to number of households + 1. + int startRange = 0; + int endRange = 0; + while ( endRange < getNumHouseholds() ) { + + endRange = startRange + NUMBER_OF_IN_MEMORY_HHS; + if ( endRange + NUMBER_OF_IN_MEMORY_HHS > getNumHouseholds() ) + endRange = getNumHouseholds(); + + HouseholdIf[] tempHhs = getHhArray( startRange, endRange-1 ); + // hhs is dimesioned to number of households + 1. + int count = 0; + for ( int r=0; r < tempHhs.length; r++ ) { + + + PersonIf[] persons = tempHhs[r].getPersons(); + + for ( int p=1; p < persons.length; p++) { + + PersonIf person = persons[p]; + + ArrayList subtourList = person.getListOfAtWorkSubtours(); + + try { + + if ( subtourList.size() == 0 ) + continue; + + for ( TourIf tour : subtourList ) { + // increment the segment count if it's the right purpose + String tourPurpose = tour.getTourPrimaryPurpose(); + if ( tourPurpose.startsWith( purposeString ) ) { + int workZone = tour.getTourOrigTaz(); + int workSubZone = tour.getTourOrigWalkSubzone(); + subtours[workZone][workSubZone] ++; + count++; + } + } + + } + catch ( RuntimeException e ) { + logger.error ( String.format("exception caught counting number of at-work subtours for purpose: %s, for household table record r=%d, personNum=%d, startRange=%d, endRange=%d, count=%d.", purposeString, r, person.getPersonNum(), startRange, endRange, count ) ); + throw e; + } + + } + + } // r (households) + + startRange += NUMBER_OF_IN_MEMORY_HHS; + + } + + return subtours; + } + + /** + * Assigns each individual person their own value of time, + * drawing from a lognormal distribution as a function of income. + */ + protected void setDistributedValuesOfTime () { + + // read in values from property file + setValueOfTimePropertyFileValues(); + + // set up the probability distributions + for (int i=0; i < valueOfTimeDistribution.length; i++) { + double mu = Math.log(meanValueOfTime[i] * meanValueOfTimeMultiplierBeforeLogForMu); + valueOfTimeDistribution[i] = new LognormalDist(mu, valueOfTimeLognormalSigma); + } + + for(int i=0; i < fullHhArray.length; ++i){ + + HouseholdIf household = fullHhArray[i]; + + // each HH gets a VOT for consistency + double rnum = household.getHhRandom().nextDouble(); + int incomeCategory = getIncomeIndexForValueOfTime( household.getIncomeInDollars() ); + double hhValueOfTime = valueOfTimeDistribution[incomeCategory-1].inverseF(rnum); + + // constrain to logical min and max values + if (hhValueOfTime < minValueOfTime) hhValueOfTime = minValueOfTime; + if (hhValueOfTime > maxValueOfTime) hhValueOfTime = maxValueOfTime; + + // adults get the full value, and children 2/3 (1-based) + PersonIf[] personArray = household.getPersons(); + for (int j = 1; j < personArray.length; ++j) { + PersonIf person = personArray[j]; + + int age = person.getAge(); + if (age < 18) + person.setValueOfTime((float) hhValueOfTime * hhValueOfTimeMultiplierForPersonUnder18); + else + person.setValueOfTime((float) hhValueOfTime); + } + } + } + + /** + * Assigns each individual person their own walk preferences + */ + protected void setDistributedWalkPrefernces() throws IOException { + + //parameters + float minWalkTimeWeight = (float) 3.5; + float maxWalkTimeWeight = (float) 1.0; + float minWalkSpeed = (float) 1.0; + float maxWalkSpeed = (float) 4.0; + float minMaxWalk = (float) 0.5; + float maxMaxWalk = (float) 3.0; + int minZscore = -3; + int maxZscore = 3; + + // read in walk preferences values from file + TableDataSet walkPreferences; + String WALK_PREFERENCES_FILE_NAME = "HouseholdManager.WalkPreferences.FileName"; + String fileName = propertyMap.get( WALK_PREFERENCES_FILE_NAME ); + CSVFileReader csvReader = new CSVFileReader(); + try { + logger.info("Reading " + fileName); + walkPreferences = csvReader.readFile( new File(fileName)); + } catch (IOException e) { + logger.error ( "IOException reading file: " + WALK_PREFERENCES_FILE_NAME, e ); + throw new IOException(); + } + + // set up normal distribution + NormalDist normalDistribution = new NormalDist(); + + //loop thru hhs and persons + for(int i=0; i < fullHhArray.length; ++i) { + + HouseholdIf household = fullHhArray[i]; + PersonIf[] personArray = household.getPersons(); + + for (int j = 1; j < personArray.length; ++j) { + + PersonIf person = personArray[j]; + int age = person.getAge(); + + //get and truncate zscore value + double rnum = household.getHhRandom().nextDouble(); + float zscore = (float)normalDistribution.inverseF(rnum); + zscore = zscore < minZscore ? minZscore : zscore; + zscore = zscore > maxZscore ? maxZscore : zscore; + + //get propensities by age + walkPreferences.buildIndex(1); //age column + float min = walkPreferences.getIndexedValueAt(age, "Lower 0.5%"); + float median = walkPreferences.getIndexedValueAt(age, "Median 50%"); + float max = walkPreferences.getIndexedValueAt(age, "Upper 99.5%"); + + float propensity; + float lower_value = median + (min - median) * zscore / minZscore; + float upper_value = median + (max - median) * zscore / maxZscore; + propensity = zscore < 0 ? lower_value : upper_value; + + //parameters + float walkTime = propensity * maxWalkTimeWeight + (1 - propensity) * minWalkTimeWeight; + float walkSpeed = propensity * maxWalkSpeed + (1 - propensity) * minWalkSpeed; + float maxWalk = propensity * maxMaxWalk + (1 - propensity) * minMaxWalk; + + //set values + person.setWalkTimeWeight(walkTime); + person.setWalkSpeed(walkSpeed); + person.setMaxWalk(maxWalk); + + } + } + } + + + protected void setUserClass () { + + //parameters + double constantC1 = 1.1; + double age35pC1 = 0.06; + double income35to60C1 = 0.14; + double income60pC1 = -1.25; + double pnrC1 = -1.85; + double knrC1 = -1.62; + double workC1 = -0.61; + + double constantC2 = 0.34; + double age35pC2 = -0.24; + double income35to60C2 = 0.19; + double income60pC2 = -1.25; + double pnrC2 = -1.85; + double knrC2 = 0.34; + double workC2 = -0.71; + + //user class models + final String[] model_names = {"user_class_work_walk","user_class_work_pnr","user_class_work_knr","user_class_non_work_walk","user_class_non_work_pnr","user_class_non_work_knr"}; + + for(int i=0; i < fullHhArray.length; ++i){ + + HouseholdIf household = fullHhArray[i]; + PersonIf[] personArray = household.getPersons(); + + for (int j = 1; j < personArray.length; ++j) { + PersonIf person = personArray[j]; + + int age = person.getAge(); + int income = household.getIncomeInDollars(); + + int isAge35p = (age >= 35) ? 1 : 0; + int isIncome35to60 = (income >= 35000) & (income < 60000) ? 1 : 0; + int isIncome60p = (income >= 60000) ? 1 : 0; + + //non-work + double walkUtilC1 = constantC1 + age35pC1 * isAge35p + income35to60C1 * isIncome35to60 + income60pC1 * isIncome60p; + double pnrUtilC1 = constantC1 + age35pC1 * isAge35p + income35to60C1 * isIncome35to60 + income60pC1 * isIncome60p + pnrC1; + double knrUtilC1 = constantC1 + age35pC1 * isAge35p + income35to60C1 * isIncome35to60 + income60pC1 * isIncome60p + knrC1; + + double walkUtilC2 = constantC2 + age35pC2 * isAge35p + income35to60C2 * isIncome35to60 + income60pC2 * isIncome60p; + double pnrUtilC2 = constantC2 + age35pC2 * isAge35p + income35to60C2 * isIncome35to60 + income60pC2 * isIncome60p + pnrC2; + double knrUtilC2 = constantC2 + age35pC2 * isAge35p + income35to60C2 * isIncome35to60 + income60pC2 * isIncome60p + knrC2; + + //work + double walkUtilC1_Work = walkUtilC1 + workC1; + double pnrUtilC1_Work = pnrUtilC1 + workC1; + double knrUtilC1_Work = knrUtilC1 + workC1; + + double walkUtilC2_Work = walkUtilC2 + workC2; + double pnrUtilC2_Work = pnrUtilC2 + workC2; + double knrUtilC2_Work = knrUtilC2 + workC2; + + // draw number + double rnum = household.getHhRandom().nextDouble(); + + //create simple models + LogitModel[] models = new LogitModel[model_names.length]; + for(int k=0; k= min[i] & industryCensus <= max[i]) { + return occ[i]; + } + } + + return -1; + } + + /** + * Sets additional properties specific to MTC, included distributed value-of-time information + */ + private void setValueOfTimePropertyFileValues ( ) { + + boolean errorFlag = false; + String propertyValue = ""; + + propertyValue = propertyMap.get( PROPERTIES_MIN_VALUE_OF_TIME_KEY ); + if ( propertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_MIN_VALUE_OF_TIME_KEY + ", not able to set min value of time value." ); + errorFlag = true; + } + else + minValueOfTime = Float.parseFloat( propertyValue ); + + propertyValue = propertyMap.get( PROPERTIES_MAX_VALUE_OF_TIME_KEY ); + if ( propertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_MAX_VALUE_OF_TIME_KEY + ", not able to set max value of time value." ); + errorFlag = true; + } + else + maxValueOfTime = Float.parseFloat( propertyValue ); + + // mean values of time by income category are specified as a "comma-sparated" list of float values + // the number of mean values in the lsit determines the number of income categories for value of time + // the number of upper limit income dollar values is expected to be number of mean values - 1. + int numIncomeCategories = -1; + String meanValueOfTimesPropertyValue = propertyMap.get( PROPERTIES_MEAN_VALUE_OF_TIME_VALUES_KEY ); + if ( meanValueOfTimesPropertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_MEAN_VALUE_OF_TIME_VALUES_KEY + ", not able to set mean value of time values." ); + errorFlag = true; + } + else { + + ArrayList valueList = new ArrayList(); + StringTokenizer valueTokenizer = new StringTokenizer( meanValueOfTimesPropertyValue, "," ); + while( valueTokenizer.hasMoreTokens() ) { + String listValue = valueTokenizer.nextToken(); + float value = Float.parseFloat( listValue.trim() ); + valueList.add( value ); + } + + numIncomeCategories = valueList.size(); + meanValueOfTime = new float[numIncomeCategories]; + valueOfTimeDistribution = new LognormalDist[numIncomeCategories]; + + for ( int i=0; i < numIncomeCategories; i++ ) + meanValueOfTime[i] = valueList.get(i); + } + + // read the upper limit values for value of time income ranges. + // there should be exactly 1 less than the number of mean value of time values - any other value is an error. + String valueOfTimeIncomesPropertyValue = propertyMap.get( PROPERTIES_MEAN_VALUE_OF_TIME_INCOME_LIMITS_KEY ); + if ( valueOfTimeIncomesPropertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_MEAN_VALUE_OF_TIME_INCOME_LIMITS_KEY + ", not able to set upper limits for value of time income ranges." ); + errorFlag = true; + } + else { + + ArrayList valueList = new ArrayList(); + StringTokenizer valueTokenizer = new StringTokenizer( valueOfTimeIncomesPropertyValue, "," ); + while( valueTokenizer.hasMoreTokens() ) { + String listValue = valueTokenizer.nextToken(); + int value = Integer.parseInt( listValue.trim() ); + valueList.add( value ); + } + + int numIncomeValues = valueList.size(); + if ( numIncomeValues != (numIncomeCategories - 1) ) { + Exception e = new RuntimeException(); + logger.error( "an error occurred reading properties file values for distributed value of time calculations." ); + logger.error( "the mean value of time values property=" + meanValueOfTimesPropertyValue + " specifies " + numIncomeCategories + " mean values, thus " + numIncomeCategories + " income ranges." ); + logger.error( "the value of time income range values property=" + valueOfTimeIncomesPropertyValue + " specifies " + numIncomeValues + " income range limit values." ); + logger.error( "there should be exactly " + (numIncomeCategories-1) + " income range limit values for " + numIncomeCategories + " mean value of time values.", e ); + System.exit(-1); + } + + // set the income dollar value upper limits for value of time income ranges + incomeDollarLimitsForValueOfTime = new int[numIncomeValues+1]; + for ( int i=0; i < numIncomeValues; i++ ) + incomeDollarLimitsForValueOfTime[i] = valueList.get(i); + + incomeDollarLimitsForValueOfTime[numIncomeValues] = Integer.MAX_VALUE; + } + + propertyValue = propertyMap.get( PROPERTIES_HH_VALUE_OF_TIME_MULTIPLIER_FOR_UNDER_18_KEY ); + if ( propertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_HH_VALUE_OF_TIME_MULTIPLIER_FOR_UNDER_18_KEY + ", not able to set hh value of time multiplier for kids in hh under age 18." ); + errorFlag = true; + } + else + hhValueOfTimeMultiplierForPersonUnder18 = Float.parseFloat( propertyValue ); + + propertyValue = propertyMap.get( PROPERTIES_MEAN_VALUE_OF_TIME_MULTIPLIER_FOR_MU_KEY ); + if ( propertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_MEAN_VALUE_OF_TIME_MULTIPLIER_FOR_MU_KEY + ", not able to set lognormal distribution mu parameter multiplier." ); + errorFlag = true; + } + else + meanValueOfTimeMultiplierBeforeLogForMu = Float.parseFloat( propertyValue ); + + propertyValue = propertyMap.get( PROPERTIES_VALUE_OF_TIME_LOGNORMAL_SIGMA_KEY ); + if ( propertyValue == null ) { + logger.error( "property file key missing: " + PROPERTIES_VALUE_OF_TIME_LOGNORMAL_SIGMA_KEY + ", not able to set lognormal distribution sigma parameter." ); + errorFlag = true; + } + else + valueOfTimeLognormalSigma = Float.parseFloat( propertyValue ); + + if ( errorFlag ) { + Exception e = new RuntimeException(); + logger.error( "errors occurred reading properties file values for distributed value of time calculations.", e ); + System.exit(-1); + } + + } + + private int getIncomeIndexForValueOfTime( int incomeInDollars ) { + int returnValue = -1; + for (int i=0; i < incomeDollarLimitsForValueOfTime.length; i++ ) { + if ( incomeInDollars < incomeDollarLimitsForValueOfTime[i] ) { + // return a 1s based index value + returnValue = i + 1; + break; + } + } + + return returnValue; + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/HouseholdDataManagerIf.java b/src/java/com/pb/models/ctrampIf/HouseholdDataManagerIf.java new file mode 100644 index 0000000..1e705d8 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/HouseholdDataManagerIf.java @@ -0,0 +1,163 @@ +package com.pb.models.ctrampIf; + +import java.util.HashMap; + + +/** + * @author Jim Hicks + * + * Class for managing household and person object data read from synthetic population files. + */ +public interface HouseholdDataManagerIf { + + public String testRemote(); + + public void setPropertyFileValues ( HashMap propertyMap ); + + public void setDebugHhIdsFromHashmap (); + + public int[] getRandomOrderHhIndexArray( int numHhs ); + public int[] getHomeTazOrderHhIndexArray( int[] hhIds ); + + public void mapTablesToHouseholdObjects( String inputHouseholdFileName, String inputPersonFileName, ModelStructure modelStructure, TazDataIf tazDataManager ); + + public int getArrayIndex( int hhId ); + + public void setHhArray( HouseholdIf[] hhs ); + public void setHhArray( HouseholdIf[] tempHhs, int startIndex ); + + public void setupHouseholdDataManager( ModelStructure modelStructure, TazDataIf tazDataManager, String inputHouseholdFileName, String inputPersonFileName ); + + public int[][][] getTourPurposePersonsByHomeZone( String[] purposeList ); + public double[][][] getMandatoryToursByDestZoneSubZone(); + public int[][] getIndividualNonMandatoryToursByHomeZoneSubZone( String purposeString ); + public int[][] getJointToursByHomeZoneSubZone( String purposeString ); + public int[][] getAtWorkSubtoursByWorkZoneSubZone( String purposeString ); + + public void logPersonSummary( HouseholdIf[] hhs ); + + public void setUwslRandomCount( int iter ); + + public void setAoRandomCount(); + + public void setCdapRandomCount(); + + public void setImtfRandomCount(); + + public void setImtodRandomCount(); + + public void setAwfRandomCount(); + + public void setAwlRandomCount(); + + public void setAwtodRandomCount(); + + public void setJtfRandomCount(); + + public void setJtlRandomCount(); + + public void setJtodRandomCount(); + + public void setInmtfRandomCount(); + + public void setInmtlRandomCount(); + + public void setInmtodRandomCount(); + + public void setStfRandomCount(); + + public void setStlRandomCount(); + + public void resetUwslRandom( int iter ); + + public void resetAoRandom( int iter ); + + public void resetFpRandom(); + + public void resetCdapRandom(); + + public void resetImtfRandom(); + + public void resetImtodRandom(); + + public void resetImmcRandom(); + + public void resetAwfRandom(); + + public void resetAwlRandom(); + + public void resetAwtodRandom(); + + public void resetAwmcRandom(); + + public void resetJtfRandom(); + + public void resetJtlRandom(); + + public void resetJtodRandom(); + + public void resetJmcRandom(); + + public void resetInmtfRandom(); + + public void resetInmtlRandom(); + + public void resetInmtodRandom(); + + public void resetInmmcRandom(); + + public void resetStfRandom(); + + public void resetStlRandom(); + + + + /** + * set the hh id for which debugging info from choice models applied to this household will be logged if debug logging. + */ + public void setDebugHouseholdId( int debugHhId, boolean value ); + + /** + * Sets the HashSet used to trace households for debug purposes and sets the + * debug switch for each of the listed households. Also sets + */ + public void setTraceHouseholdSet(); + + + /** + * Sets the HashSet used to trace households for debug purposes and sets the + * debug switch for each of the listed households. Also sets + */ + public void setHouseholdSampleRate( float sampleRate, int sampleSeed ); + + + /** + * return the array of Household objects holding the synthetic population and choice model outcomes. + * @return hhs + */ + public HouseholdIf[] getHhArray(); + public HouseholdIf[] getHhArray(int firstHhIndex, int lastHhIndex); + + + /** + * return the number of household objects read from the synthetic population. + * @return + */ + public int getNumHouseholds(); + + + + /** + * set walk segment (0-none, 1-short, 2-long walk to transit access) for the origin for this tour + */ + public short getInitialOriginWalkSegment (short taz, double randomNumber); + + + + /* + public long getBytesUsedByHouseholdArray(); + + public void createSerializedHhArrayInFileFromObject( String serializedObjectFileName, String serializedObjectKey ); + public Household[] createHhArrayFromSerializedObjectInFile( String serializedObjectFileName, String serializedObjectKey ); + */ +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/HouseholdDataManagerRmi.java b/src/java/com/pb/models/ctrampIf/HouseholdDataManagerRmi.java new file mode 100644 index 0000000..750b9eb --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/HouseholdDataManagerRmi.java @@ -0,0 +1,409 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + + +/** + * @author Jim Hicks + * + * Class for managing household and person object data read from synthetic population files. + */ +public class HouseholdDataManagerRmi implements HouseholdDataManagerIf, Serializable { + + UtilRmi remote; + String connectString; + + + + public HouseholdDataManagerRmi( String hostname, int port, String className ){ + + connectString = String.format("//%s:%d/%s", hostname, port, className ); + remote = new UtilRmi(connectString); + + } + + public void setPropertyFileValues ( HashMap propertyMap ) { + Object[] objArray = { propertyMap }; + remote.method( "setPropertyFileValues", objArray); + } + + public void setDebugHhIdsFromHashmap () { + Object[] objArray = {}; + remote.method( "setDebugHhIdsFromHashmap", objArray); + } + + public void setupHouseholdDataManager(ModelStructure modelStructure, TazDataIf tazDataManager, String inputHouseholdFileName, String inputPersonFileName ){ + Object[] objArray = { modelStructure, tazDataManager, inputHouseholdFileName, inputPersonFileName }; + remote.method( "setupHouseholdDataManager", objArray); + } + + public void logPersonSummary( HouseholdIf[] hhs ) { + Object[] objArray = { hhs }; + remote.method( "logPersonSummary", objArray); + } + + public int getArrayIndex( int hhId ) { + Object[] objArray = { hhId }; + return (Integer)remote.method( "getArrayIndex", objArray); + } + + public double[][][] getMandatoryToursByDestZoneSubZone() { + Object[] objArray = {}; + return (double[][][])remote.method( "getMandatoryToursByDestZoneSubZone", objArray); + } + + public int[][][] getTourPurposePersonsByHomeZone( String[] purposeList ) { + Object[] objArray = { purposeList }; + return (int[][][])remote.method( "getTourPurposePersonsByHomeZone", objArray); + } + + public int[][] getIndividualNonMandatoryToursByHomeZoneSubZone( String purposeString ) { + Object[] objArray = { purposeString }; + return (int[][])remote.method( "getIndividualNonMandatoryToursByHomeZoneSubZone", objArray); + } + + public int[][] getJointToursByHomeZoneSubZone( String purposeString ) { + Object[] objArray = { purposeString }; + return (int[][])remote.method( "getJointToursByHomeZoneSubZone", objArray); + } + + public int[][] getAtWorkSubtoursByWorkZoneSubZone( String purposeString ) { + Object[] objArray = { purposeString }; + return (int[][])remote.method( "getAtWorkSubtoursByWorkZoneSubZone", objArray); + } + + public String testRemote() { + Object[] objArray = {}; + return (String)remote.method( "testRemote", objArray); + } + + public void mapTablesToHouseholdObjects() { + Object[] objArray = {}; + remote.method( "mapTablesToHouseholdObjects", objArray); + } + + public void mapTablesToHouseholdObjects( String inputHouseholdFileName, String inputPersonFileName, ModelStructure modelStructure, TazDataIf tazDataManager ) { + Object[] objArray = { inputHouseholdFileName, inputPersonFileName, modelStructure, tazDataManager }; + remote.method( "mapTablesToHouseholdObjects", objArray); + } + + public void writeResultData () { + Object[] objArray = {}; + remote.method( "writeResultData", objArray); + } + + public int[] getRandomOrderHhIndexArray( int numHhs ) { + Object[] objArray = { numHhs }; + return (int[])remote.method( "getRandomOrderHhIndexArray", objArray); + } + + public int[] getHomeTazOrderHhIndexArray( int[] hhIds ) { + Object[] objArray = { hhIds }; + return (int[])remote.method( "getHomeTazOrderHhIndexArray", objArray); + } + + + /** + * set the hh id for which debugging info from choice models applied to this household will be logged if debug logging. + */ + public void setDebugHouseholdId( int debugHhId, boolean value ) { + Object[] objArray = { debugHhId, value }; + remote.method( "setDebugHouseholdId", objArray); + } + + /** + * Sets the HashSet used to trace households for debug purposes and sets the + * debug switch for each of the listed households. Also sets + */ + public void setTraceHouseholdSet(){ + Object[] objArray = {}; + remote.method( "setTraceHouseholdSet", objArray); + } + + public void setHouseholdSampleRate( float sampleRate, int sampleSeed ){ + Object[] objArray = { sampleRate, sampleSeed }; + remote.method( "setHouseholdSampleRate", objArray); + } + + public void setUwslRandomCount( int iter ) { + Object[] objArray = { iter }; + remote.method( "setUwslRandomCount", objArray); + } + + public void setAoRandomCount() { + Object[] objArray = {}; + remote.method( "setAoRandomCount", objArray); + } + + public void setFpRandomCount() { + Object[] objArray = {}; + remote.method( "setFpRandomCount", objArray); + } + + public void setCdapRandomCount() { + Object[] objArray = {}; + remote.method( "setCdapRandomCount", objArray); + } + + public void setImtfRandomCount() { + Object[] objArray = {}; + remote.method( "setImtfRandomCount", objArray); + } + + public void setImtodRandomCount() { + Object[] objArray = {}; + remote.method( "setImtodRandomCount", objArray); + } + + public void setImmcRandomCount() { + Object[] objArray = {}; + remote.method( "setImmcRandomCount", objArray); + } + + public void setAwfRandomCount() { + Object[] objArray = {}; + remote.method( "setAwfRandomCount", objArray); + } + + public void setAwlRandomCount() { + Object[] objArray = {}; + remote.method( "setAwlRandomCount", objArray); + } + + public void setAwtodRandomCount() { + Object[] objArray = {}; + remote.method( "setAwtodRandomCount", objArray); + } + + public void setAwmcRandomCount() { + Object[] objArray = {}; + remote.method( "setAwmcRandomCount", objArray); + } + + public void setJtfRandomCount() { + Object[] objArray = {}; + remote.method( "setJtfRandomCount", objArray); + } + + public void setJtlRandomCount() { + Object[] objArray = {}; + remote.method( "setJtlRandomCount", objArray); + } + + public void setJtodRandomCount() { + Object[] objArray = {}; + remote.method( "setJtodRandomCount", objArray); + } + + public void setJmcRandomCount() { + Object[] objArray = {}; + remote.method( "setJmcRandomCount", objArray); + } + + public void setInmtfRandomCount() { + Object[] objArray = {}; + remote.method( "setInmtfRandomCount", objArray); + } + + public void setInmtlRandomCount() { + Object[] objArray = {}; + remote.method( "setInmtlRandomCount", objArray); + } + + public void setInmtodRandomCount() { + Object[] objArray = {}; + remote.method( "setInmtodRandomCount", objArray); + } + + public void setInmmcRandomCount() { + Object[] objArray = {}; + remote.method( "setInmmcRandomCount", objArray); + } + + public void setStfRandomCount() { + Object[] objArray = {}; + remote.method( "setStfRandomCount", objArray); + } + + public void setStlRandomCount() { + Object[] objArray = {}; + remote.method( "setStlRandomCount", objArray); + } + + public void resetUwslRandom( int iter ) { + Object[] objArray = { iter }; + remote.method( "resetUwslRandom", objArray); + } + + public void resetAoRandom( int iter ) { + Object[] objArray = { iter }; + remote.method( "resetAoRandom", objArray); + } + + public void resetFpRandom() { + Object[] objArray = {}; + remote.method( "resetFpRandom", objArray); + } + + public void resetCdapRandom() { + Object[] objArray = {}; + remote.method( "resetCdapRandom", objArray); + } + + public void resetImtfRandom() { + Object[] objArray = {}; + remote.method( "resetImtfRandom", objArray); + } + + public void resetImtodRandom() { + Object[] objArray = {}; + remote.method( "resetImtodRandom", objArray); + } + + public void resetImmcRandom() { + Object[] objArray = {}; + remote.method( "resetImmcRandom", objArray); + } + + public void resetAwfRandom() { + Object[] objArray = {}; + remote.method( "resetAwfRandom", objArray); + } + + public void resetAwlRandom() { + Object[] objArray = {}; + remote.method( "resetAwlRandom", objArray); + } + + public void resetAwtodRandom() { + Object[] objArray = {}; + remote.method( "resetAwtodRandom", objArray); + } + + public void resetAwmcRandom() { + Object[] objArray = {}; + remote.method( "resetAwmcRandom", objArray); + } + + public void resetJtfRandom() { + Object[] objArray = {}; + remote.method( "resetJtfRandom", objArray); + } + + public void resetJtlRandom() { + Object[] objArray = {}; + remote.method( "resetJtlRandom", objArray); + } + + public void resetJtodRandom() { + Object[] objArray = {}; + remote.method( "resetJtodRandom", objArray); + } + + public void resetJmcRandom() { + Object[] objArray = {}; + remote.method( "resetJmcRandom", objArray); + } + + public void resetInmtfRandom() { + Object[] objArray = {}; + remote.method( "resetInmtfRandom", objArray); + } + + public void resetInmtlRandom() { + Object[] objArray = {}; + remote.method( "resetInmtlRandom", objArray); + } + + public void resetInmtodRandom() { + Object[] objArray = {}; + remote.method( "resetInmtodRandom", objArray); + } + + public void resetInmmcRandom() { + Object[] objArray = {}; + remote.method( "resetInmmcRandom", objArray); + } + + public void resetStfRandom() { + Object[] objArray = {}; + remote.method( "resetStfRandom", objArray); + } + + public void resetStlRandom() { + Object[] objArray = {}; + remote.method( "resetStlRandom", objArray); + } + + + /** + * return the array of Household objects holding the synthetic population and choice model outcomes. + * @return hhs + */ + public HouseholdIf[] getHhArray() { + Object[] objArray = {}; + return (HouseholdIf[])remote.method( "getHhArray", objArray); + } + + public HouseholdIf[] getHhArray(int first, int last) { + Object[] objArray = { first, last }; + return (HouseholdIf[])remote.method( "getHhArray", objArray); + } + + public void setHhArray( HouseholdIf[] hhs ) { + Object[] objArray = { hhs }; + remote.method( "setHhArray", objArray); + } + + public void setHhArray( HouseholdIf[] tempHhs, int startIndex ) { + Object[] objArray = { tempHhs, startIndex }; + remote.method( "setHhArray", objArray); + } + + + /** + * return the array of Household objects holding the synthetic population and choice model outcomes. + * @return hhs + */ + public int[] getHhIndexArray() { + Object[] objArray = {}; + return (int[])remote.method( "getHhIndexArray", objArray); + } + + /** + * return the number of household objects read from the synthetic population. + * @return number of households in synthetic population + */ + public int getNumHouseholds() { + Object[] objArray = {}; + return (Integer)remote.method( "getNumHouseholds", objArray); + } + + + /** + * set walk segment (0-none, 1-short, 2-long walk to transit access) for the origin for this tour + */ + public short getInitialOriginWalkSegment (short taz, double randomNumber) { + Object[] objArray = { taz, randomNumber }; + return (Short)remote.method( "getInitialOriginWalkSegment", objArray); + } + + public long getBytesUsedByHouseholdArray() { + Object[] objArray = {}; + return (Long)remote.method( "getBytesUsedByHouseholdArray", objArray); + } + + + public void createSerializedHhArrayInFileFromObject( String serializedObjectFileName, String serializedObjectKey ) { + Object[] objArray = { serializedObjectFileName, serializedObjectKey }; + remote.method( "createSerializedHhArrayInFileFromObject", objArray); + } + + + public HouseholdIf[] createHhArrayFromSerializedObjectInFile( String serializedObjectFileName, String serializedObjectKey ) { + Object[] objArray = { serializedObjectFileName, serializedObjectKey }; + return (HouseholdIf[])remote.method( "createHhArrayFromSerializedObjectInFile", objArray); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/HouseholdDataWriter.java b/src/java/com/pb/models/ctrampIf/HouseholdDataWriter.java new file mode 100644 index 0000000..7efd106 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/HouseholdDataWriter.java @@ -0,0 +1,1801 @@ +package com.pb.models.ctrampIf; + +import com.pb.common.calculator.VariableTable; +import com.pb.common.util.ResourceUtil; +import com.pb.common.newmodel.ChoiceModelApplication; +import com.pb.models.ctrampIf.jppf.CtrampApplication; +import com.pb.models.ctrampIf.jppf.StopLocationModeChoiceModel; +import com.pb.models.ctrampIf.sqlite.ConnectionHelper; + +import java.util.*; +import java.io.PrintWriter; +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Connection; +import java.sql.Statement; +import java.sql.PreparedStatement; + +import org.apache.log4j.Logger; + +/** + * @author crf
+ * Started: Dec 31, 2008 11:46:36 AM + */ +public class HouseholdDataWriter { + + private transient Logger logger = Logger.getLogger(HouseholdDataWriter.class); + + private static final String PROPERTIES_HOUSEHOLD_DATA_FILE = "Results.HouseholdDataFile"; + private static final String PROPERTIES_PERSON_DATA_FILE = "Results.PersonDataFile"; + private static final String PROPERTIES_INDIV_TOUR_DATA_FILE = "Results.IndivTourDataFile"; + private static final String PROPERTIES_JOINT_TOUR_DATA_FILE = "Results.JointTourDataFile"; + private static final String PROPERTIES_INDIV_TRIP_DATA_FILE = "Results.IndivTripDataFile"; + private static final String PROPERTIES_JOINT_TRIP_DATA_FILE = "Results.JointTripDataFile"; + private static final String PROPERTIES_TRIP_DATA_FILE = "Results.TripDataFile"; + private static final String PROPERTIES_TRAVEL_TIME_DATA_FILE = "Results.TravelTimeDataFile"; + private static final String PROPERTIES_TRAVEL_TIME_FORMAT = "Results.TravelTimeFormat"; + + private static final String PROPERTIES_HOUSEHOLD_TABLE = "Results.HouseholdTable"; + private static final String PROPERTIES_PERSON_TABLE = "Results.PersonTable"; + private static final String PROPERTIES_INDIV_TOUR_TABLE = "Results.IndivTourTable"; + private static final String PROPERTIES_JOINT_TOUR_TABLE = "Results.JointTourTable"; + private static final String PROPERTIES_INDIV_TRIP_TABLE = "Results.IndivTripTable"; + private static final String PROPERTIES_JOINT_TRIP_TABLE = "Results.JointTripTable"; + + private static final int NUM_WRITE_PACKETS = 2000; + + private final String intFormat = "%d"; + private final String floatFormat = "%f"; + private final String doubleFormat = "%f"; + private final String fileStringFormat = "%s"; + private final String databaseStringFormat = "'%s'"; + private String stringFormat = fileStringFormat; + + private boolean saveUtilsProbsFlag = false; + + private ResourceBundle resourceBundle; + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + private int iteration; + private TravelTimeModel travelTimeModel; + private CtrampDmuFactoryIf dmuFactory; + + private Map> tourModeAltLabels; //purpose -> mode id -> mode name + private Map> tripModeAltLabels; //trip mode choice purpose index -> mode id -> mode name; + + + + public HouseholdDataWriter( ResourceBundle resourceBundle, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, int iteration ) { + + logger.info("Writing data structures to files."); + this.resourceBundle = resourceBundle; + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + this.dmuFactory = dmuFactory; + this.iteration = iteration; + + // default is to not save the tour mode choice utils and probs for each tour + String saveUtilsProbsString = resourceBundle.getString( CtrampApplication.PROPERTIES_SAVE_TOUR_MODE_CHOICE_UTILS ); + if ( saveUtilsProbsString != null ) { + if ( saveUtilsProbsString.equalsIgnoreCase( "true" ) ) + saveUtilsProbsFlag = true; + } + + } + + //NOTE - this method should not be called simultaneously with the file one one as the string format is changed + public void writeDataToDatabase(HouseholdDataManagerIf householdData, String dbFileName) { + logger.info("Writing data structures to database."); + long t = System.currentTimeMillis(); + stringFormat = databaseStringFormat; + writeData(householdData,new DatabaseDataWriter(dbFileName)); + float delta = ((Long) (System.currentTimeMillis() - t)).floatValue() / 60000.0f; + logger.info("Finished writing data structures to database (" + delta + " minutes)."); + } + //NOTE - this method should not be called simultaneously with the database one one as the string format is changed + public void writeDataToFiles(HouseholdDataManagerIf householdData) { + stringFormat = fileStringFormat; + FileDataWriter fdw = new FileDataWriter(); + writeData(householdData,fdw); + } + + + private void writeData(HouseholdDataManagerIf householdDataManager, DataWriter writer) { + int hhid=0; + int persNum = 0; + int tourid = 0; + + boolean fileWriter = writer instanceof FileDataWriter; //only write trips if writing to file + + if (writer.getWriteTripFileFlag()) { + loadTourModes(resourceBundle,dmuFactory); + loadTripModes(resourceBundle,dmuFactory); + } + + if (writer.getWriteTravelTimesFileFlag() || writer.getWriteTripFileFlag()) { + travelTimeModel = new TravelTimeModel(ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle)); + } + + try { + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + long maxSize = 0; + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for (HouseholdIf hh : householdArray) { + if (hh == null) continue; + hhid = hh.getHhId(); + + long size = hh.getHouseholdObjectSize(); + if ( size > maxSize ) + maxSize = size; + + + writer.writeHouseholdData(formHouseholdDataEntry(hh)); + for (PersonIf p : hh.getPersons()) { + if (p == null) continue; + persNum = p.getPersonNum(); + + writer.writePersonData(formPersonDataEntry(p)); + for (TourIf t : p.getListOfWorkTours()) + writeIndivTourData(t,writer); + for (TourIf t : p.getListOfSchoolTours()) + writeIndivTourData(t,writer); + for (TourIf t : p.getListOfIndividualNonMandatoryTours()) + writeIndivTourData(t,writer); + for (TourIf t : p.getListOfAtWorkSubtours()) + writeIndivTourData(t,writer); + } + TourIf[] jointTours = hh.getJointTourArray(); + if (jointTours != null) { + for (TourIf t : jointTours) { + if (t == null) continue; + writeJointTourData(t,writer); + } + } + + if (fileWriter && writer.getWriteTripFileFlag()) { + writer.writeTripData(createVizTripRecords(hh)); + } + } + } + + logger.info( "max size for all Household objects after writing output files is " + maxSize + " bytes." ); + + if (fileWriter && writer.getWriteTravelTimesFileFlag()) { + logger.info("Writing travel time table"); + int[] tazs = tazDataManager.getIndexToZoneArray(); + writer.writeTravelTimeData(Arrays.copyOfRange(tazs,1,tazs.length)); + } + + } catch ( RuntimeException e ) { + logger.error( String.format( "error writing hh=%d, persNum=%d, tourId=%d", hhid, persNum, tourid ), e); + throw new RuntimeException(); + } finally { + writer.finishActions(); + } + } + + + + + private void writeIndivTourData(TourIf t, DataWriter writer) { + writer.writeIndivTourData(formIndivTourDataEntry(t)); + + StopIf[] outboundStops = t.getOutboundStops(); + if ( outboundStops != null ) { + for ( int i=0; i < outboundStops.length; i++ ) { + writer.writeIndivTripData(formIndivTripDataEntry(outboundStops[i])); + } + } + else { + writer.writeIndivTripData(formTourAsIndivTripDataEntry(t, false)); + } + + StopIf[] inboundStops = t.getInboundStops(); + if ( inboundStops != null ) { + for ( StopIf s : inboundStops ) + writer.writeIndivTripData(formIndivTripDataEntry(s)); + } + else { + writer.writeIndivTripData(formTourAsIndivTripDataEntry(t, true)); + } + + } + + + private void writeJointTourData(TourIf t, DataWriter writer) { + writer.writeJointTourData(formJointTourDataEntry(t)); + + StopIf[] outboundStops = t.getOutboundStops(); + if ( outboundStops != null ) { + for ( StopIf s : outboundStops ) + writer.writeJointTripData(formJointTripDataEntry(s)); + } + else { + writer.writeJointTripData(formTourAsJointTripDataEntry(t, false)); + } + + StopIf[] inboundStops = t.getInboundStops(); + if ( inboundStops != null ) { + for ( StopIf s : inboundStops ) + writer.writeJointTripData(formJointTripDataEntry(s)); + } + else { + writer.writeJointTripData(formTourAsJointTripDataEntry(t, true)); + } + + } + + + private String string(int value) { + return String.format(intFormat,value); + } + + private String string(float value) { + return String.format(floatFormat,value); + } + + private String string(double value) { + return String.format(doubleFormat,value); + } + + private String string(String value) { + return String.format(stringFormat,value); + } + + private List formHouseholdColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("maz"); + data.add("walk_subzone"); + data.add("income"); + data.add("autos"); + data.add("jtf_choice"); + data.add("size"); + data.add("workers"); + data.add("auto_suff"); + return data; + } + + + private List formHouseholdColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + return data; + } + + private List formHouseholdDataEntry(HouseholdIf hh) { + + String suff = "nocars"; + if(hh.getAutoOwnershipModelResult() > 0) { + int diff = hh.getAutoOwnershipModelResult() - hh.getWorkers(); + suff = diff < 0 ? "cars=wkrs"; + } + + List data = new LinkedList(); + data.add(string(hh.getHhId())); + data.add(string(hh.getHhTaz())); + data.add(string(hh.getHhWalkSubzone())); + data.add(string(hh.getIncomeInDollars())); + data.add(string(hh.getAutoOwnershipModelResult())); + data.add(string(hh.getJointTourFreqChosenAlt())); + data.add(string(hh.getSize())); + data.add(string(hh.getWorkers())); + data.add(suff); + return data; + } + + private List formPersonColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("person_id"); + data.add("person_num"); + data.add("age"); + data.add("gender"); + data.add("type"); + data.add("value_of_time"); + data.add("fp_choice"); + data.add("activity_pattern"); + data.add("imf_choice"); + data.add("inmf_choice"); + + data.add("walk_time_weight"); + data.add("walk_speed"); + data.add("max_walk"); + + data.add("user_class_work_walk"); + data.add("user_class_work_pnr"); + data.add("user_class_work_knr"); + data.add("user_class_non_work_walk"); + data.add("user_class_non_work_pnr"); + data.add("user_class_non_work_knr"); + + return data; + } + + private List formPersonColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.REAL); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + + data.add(SqliteDataTypes.REAL); + data.add(SqliteDataTypes.REAL); + data.add(SqliteDataTypes.REAL); + + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + + return data; + } + + private List formPersonDataEntry(PersonIf p) { + List data = new LinkedList(); + data.add(string(p.getHouseholdObject().getHhId())); + data.add(string(p.getPersonId())); + data.add(string(p.getPersonNum())); + data.add(string(p.getAge())); + data.add(string(p.getPersonIsMale() == 1 ? "m" : "f")); + data.add(string(p.getPersonType())); + data.add(string(p.getValueOfTime())); + data.add(string(p.getFreeParkingAvailableResult())); + data.add(string(p.getCdapActivity())); + data.add(string(p.getImtfChoice())); + data.add(string(p.getInmtfChoice())); + + data.add(string(p.getWalkTimeWeight())); + data.add(string(p.getWalkSpeed())); + data.add(string(p.getMaxWalk())); + + data.add(string(p.getUserClass("user_class_work_walk"))); + data.add(string(p.getUserClass("user_class_work_pnr"))); + data.add(string(p.getUserClass("user_class_work_knr"))); + + data.add(string(p.getUserClass("user_class_non_work_walk"))); + data.add(string(p.getUserClass("user_class_non_work_pnr"))); + data.add(string(p.getUserClass("user_class_non_work_knr"))); + + return data; + } + + private List formIndivTourColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("person_id"); + data.add("person_num"); + data.add("person_type"); + data.add("tour_id"); + data.add("tour_category"); + data.add("tour_purpose"); + data.add("orig_maz"); + data.add("orig_walk_segment"); + data.add("dest_maz"); + data.add("dest_walk_segment"); + data.add("depart_period"); + data.add("arrive_period"); + data.add("tour_mode"); + data.add("atWork_freq"); + data.add("num_ob_stops"); + data.add("num_ib_stops"); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + for ( int i=1; i <= numModeAlts; i++ ) { + String colName = String.format( "util_%d", i ); + data.add( colName ); + } + + for ( int i=1; i <= numModeAlts; i++ ) { + String colName = String.format( "prob_%d", i ); + data.add( colName ); + } + } + + return data; + } + + private List formJointTourColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("tour_id"); + data.add("tour_category"); + data.add("tour_purpose"); + data.add("tour_composition"); + data.add("tour_participants"); + data.add("orig_maz"); + data.add("orig_walk_segment"); + data.add("dest_maz"); + data.add("dest_walk_segment"); + data.add("depart_period"); + data.add("arrive_period"); + data.add("tour_mode"); + data.add("num_ob_stops"); + data.add("num_ib_stops"); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + for ( int i=1; i <= numModeAlts; i++ ) { + String colName = String.format( "util_%d", i ); + data.add( colName ); + } + + for ( int i=1; i <= numModeAlts; i++ ) { + String colName = String.format( "prob_%d", i ); + data.add( colName ); + } + } + + return data; + } + + private List formIndivTourColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + for ( int i=1; i <= numModeAlts; i++ ) { + data.add( SqliteDataTypes.REAL ); + } + + for ( int i=1; i <= numModeAlts; i++ ) { + data.add( SqliteDataTypes.REAL ); + } + } + + return data; + } + + private List formJointTourColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + for ( int i=1; i <= numModeAlts; i++ ) { + data.add( SqliteDataTypes.REAL ); + } + + for ( int i=1; i <= numModeAlts; i++ ) { + data.add( SqliteDataTypes.REAL ); + } + } + + return data; + } + + private List formIndivTourDataEntry(TourIf t) { + + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getPersonObject().getPersonId())); + data.add(string(t.getPersonObject().getPersonNum())); + data.add(string(t.getPersonObject().getPersonTypeNumber())); + data.add(string(t.getTourId())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + data.add(string(t.getTourPrimaryPurpose())); + data.add(string(t.getTourOrigTaz())); + data.add(string(t.getTourOrigWalkSubzone())); + data.add(string(t.getTourDestTaz())); + data.add(string(t.getTourDestWalkSubzone())); + data.add(string(t.getTourDepartPeriod())); + data.add(string(t.getTourArrivePeriod())); + data.add(string(t.getTourModeChoice())); + data.add(string(t.getSubtourFreqChoice())); + data.add(string( t.getNumOutboundStops() == 0 ? 0 : t.getNumOutboundStops()) ); + data.add(string( t.getNumInboundStops() == 0 ? 0 : t.getNumInboundStops()) ); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + float[] utils = t.getTourModalUtilities(); + for ( int i=0; i < utils.length; i++ ) + data.add(string(utils[i])); + for ( int i=utils.length; i < numModeAlts; i++ ) + data.add( "-999" ); + + float[] probs = t.getTourModalProbabilities(); + for ( int i=0; i < probs.length; i++ ) + data.add(string(probs[i])); + for ( int i=probs.length; i < numModeAlts; i++ ) + data.add( "0.0" ); + } + + return data; + } + + private List formJointTourDataEntry(TourIf t) { + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getTourId())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + data.add(string(t.getTourPrimaryPurpose())); + data.add(string(t.getJointTourComposition())); + data.add(string(formTourParticipationEntry(t))); + data.add(string(t.getTourOrigTaz())); + data.add(string(t.getTourOrigWalkSubzone())); + data.add(string(t.getTourDestTaz())); + data.add(string(t.getTourDestWalkSubzone())); + data.add(string(t.getTourDepartPeriod())); + data.add(string(t.getTourArrivePeriod())); + data.add(string(t.getTourModeChoice())); + data.add(string( t.getNumOutboundStops() == 0 ? 0 : t.getNumOutboundStops()) ); + data.add(string( t.getNumInboundStops() == 0 ? 0 : t.getNumInboundStops()) ); + + if ( saveUtilsProbsFlag ) { + int numModeAlts = modelStructure.getMaxTourModeIndex(); + + float[] utils = t.getTourModalUtilities(); + if ( utils != null ) { + for ( int i=0; i < utils.length; i++ ) + data.add(string(utils[i])); + + if ( utils.length < numModeAlts ) + for ( int i=utils.length; i < numModeAlts; i++ ) + data.add( "-999" ); + } + else { + for ( int i=0; i < numModeAlts; i++ ) + data.add( "-999" ); + } + + float[] probs = t.getTourModalProbabilities(); + if ( probs != null ) { + for ( int i=0; i < probs.length; i++ ) + data.add(string(probs[i])); + + if ( probs.length < numModeAlts ) + for ( int i=probs.length; i < numModeAlts; i++ ) + data.add( "0.0" ); + } + else { + for ( int i=0; i < numModeAlts; i++ ) + data.add( "0.0" ); + } + + } + + return data; + } + + private String formTourParticipationEntry(TourIf t) { + byte[] persons = t.getPersonNumArray(); + if (persons == null) + throw new RuntimeException("null Person[] object for joint tour, hhid=" + t.getHhId()); + if (persons.length == 1) + throw new RuntimeException("Person[] object has length=1 for joint tour, hhid=" + t.getHhId()); + String participation = Integer.toString( persons[0] ); + for (int i=1; i < persons.length; i++ ) { + participation += " "; + participation += persons[i]; + } + return participation; + } + + + private List formIndivTripColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("person_id"); + data.add("person_num"); + data.add("tour_id"); + data.add("stop_id"); + data.add("inbound"); + data.add("tour_purpose"); + data.add("orig_purpose"); + data.add("dest_purpose"); + data.add("orig_maz"); + data.add("orig_walk_segment"); + data.add("dest_maz"); + data.add("dest_walk_segment"); + data.add("parking_taz"); + data.add("stop_period"); + data.add("trip_mode"); + data.add("tour_mode"); + data.add("tour_category"); + + data.add("board_tap"); + data.add("alight_tap"); + + data.add("orig_taz"); + data.add("dest_taz"); + + + return data; + } + + private List formJointTripColumnNames() { + List data = new LinkedList(); + data.add("hh_id"); + data.add("tour_id"); + data.add("stop_id"); + data.add("inbound"); + data.add("tour_purpose"); + data.add("orig_purpose"); + data.add("dest_purpose"); + data.add("orig_maz"); + data.add("orig_walk_segment"); + data.add("dest_maz"); + data.add("dest_walk_segment"); + data.add("parking_taz"); + data.add("stop_period"); + data.add("trip_mode"); + data.add("num_participants"); + data.add("tour_mode"); + data.add("tour_category"); + + data.add("board_tap"); + data.add("alight_tap"); + + data.add("orig_taz"); + data.add("dest_taz"); + + return data; + } + + private String formTripTableColumnHeader() { + return new StringBuilder() + .append("hh_id").append(",") + .append("person_id").append(",") + .append("person_num").append(",") + .append("tour_id").append(",") + .append("stop_id").append(",") + .append("inbound").append(",") + .append("tour_category").append(",") + .append("tour_purpose").append(",") + .append("orig_purpose").append(",") + .append("dest_purpose").append(",") + .append("orig_maz").append(",") + .append("dest_maz").append(",") + .append("orig_walk_segment").append(",") + .append("dest_walk_segment").append(",") + .append("parking_taz").append(",") + .append("stop_period").append(",") + .append("trip_mode").append(",") + .append("tour_mode").append(",") + .append("num_participants").append(",") + .append("tour_participants").append(",") + .append("tour_depart_period").append(",") + .append("tour_id_uniq").append(",") + .append("trip_id").append(",") + .append("orig_purpose").append(",") + .append("home_taz").append(",") + .append("hh_income").append(",") + .append("hh_autos").append(",") + .append("hh_fp_choice").append(",") + .append("hh_inc_bin").append(",") + .append("hh_size").append(",") + .append("hh_wkrs").append(",") + .append("hh_auto_suff").append(",") + .append("age").append(",") + .append("gender").append(",") + .append("person_type").append(",") + .append("activity_pattern").append(",") + .append("tour_mode_name").append(",") + .append("trip_mode_name").append(",") + .append("travel_time").toString(); + } + + private String formTravelTimeTableColumnHeader() { + return new StringBuilder() + .append("orig_taz").append(",") + .append("dest_taz").append(",") + .append("time_of_day").append(",") + .append("mode_name").append(",") + .append("travel_time").toString(); + } + + private List formIndivTripColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + return data; + } + + private List formJointTripColumnTypes() { + List data = new LinkedList(); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.TEXT); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + data.add(SqliteDataTypes.INTEGER); + return data; + } + + private List formIndivTripDataEntry(StopIf s) { + TourIf t = s.getTour(); + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getPersonObject().getPersonId())); + data.add(string(t.getPersonObject().getPersonNum())); + data.add(string(t.getTourId())); + data.add(string(s.getStopId())); + data.add(string(s.isInboundStop() ? 1 : 0)); + data.add(string(t.getTourPrimaryPurpose())); + + if ( s.getStopId() == 0 ) { + if ( s.isInboundStop() ) { + // first trip on inbound half-tour with stops + data.add( s.getOrigPurpose() ); + data.add( s.getDestPurpose() ); + } + else { + // first trip on outbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add("Work"); + data.add( s.getDestPurpose() ); + } + else { + data.add("Home"); + data.add( s.getDestPurpose() ); + } + } + } + else if ( s.isInboundStop() && s.getStopId() == t.getNumInboundStops() ) { + // last trip on inbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add( s.getOrigPurpose() ); + data.add("Work"); + } + else { + data.add( s.getOrigPurpose() ); + data.add("Home"); + } + } + else if ( ! s.isInboundStop() && s.getStopId() == t.getNumOutboundStops() ) { + // last trip on outbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add( s.getOrigPurpose() ); + data.add(t.getTourPrimaryPurpose()); + } + else { + data.add( s.getOrigPurpose() ); + data.add(t.getTourPrimaryPurpose()); + } + } + else { + data.add( s.getOrigPurpose() ); + data.add( s.getDestPurpose() ); + } + + data.add(string(s.getOrig())); + data.add(string(s.getOrigWalkSegment())); + data.add(string(s.getDest())); + data.add(string(s.getDestWalkSegment())); + data.add(string(s.getPark())); + data.add(string(s.getStopPeriod())); + data.add(string(s.getMode())); + data.add(string(t.getTourModeChoice())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + + data.add(string(s.getBTap())); + data.add(string(s.getATap())); + + data.add(string(tazDataManager.getTazsForMazs()[s.getOrig()-1])); + data.add(string(tazDataManager.getTazsForMazs()[s.getDest()-1])); + + return data; + } + + + private List formJointTripDataEntry(StopIf s) { + TourIf t = s.getTour(); + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getTourId())); + data.add(string(s.getStopId())); + data.add(string(s.isInboundStop() ? 1 : 0)); + data.add(string(t.getTourPrimaryPurpose())); + + if ( s.getStopId() == 0 ) { + if ( s.isInboundStop() ) { + // first trip on inbound half-tour with stops + data.add( s.getOrigPurpose() ); + data.add( s.getDestPurpose() ); + } + else { + // first trip on outbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add("Work"); + data.add( s.getDestPurpose() ); + } + else { + data.add("Home"); + data.add( s.getDestPurpose() ); + } + } + } + else if ( s.isInboundStop() && s.getStopId() == t.getNumInboundStops() ) { + // last trip on inbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add( s.getOrigPurpose() ); + data.add("Work"); + } + else { + data.add( s.getOrigPurpose() ); + data.add("Home"); + } + } + else if ( ! s.isInboundStop() && s.getStopId() == t.getNumOutboundStops() ) { + // last trip on outbound half-tour with stops + if ( t.getTourCategoryIsAtWork() ) { + data.add( s.getOrigPurpose() ); + data.add(t.getTourPrimaryPurpose()); + } + else { + data.add( s.getOrigPurpose() ); + data.add(t.getTourPrimaryPurpose()); + } + } + else { + data.add( s.getOrigPurpose() ); + data.add( s.getDestPurpose() ); + } + + data.add(string(s.getOrig())); + data.add(string(s.getOrigWalkSegment())); + data.add(string(s.getDest())); + data.add(string(s.getDestWalkSegment())); + data.add(string(s.getPark())); + data.add(string(s.getStopPeriod() )); + data.add(string(s.getMode())); + + byte[] participants = t.getPersonNumArray(); + if ( participants == null ) { + logger.error ( "tour participants array is null, hhid=" + t.getHhId() + "." ); + throw new RuntimeException(); + } + if ( participants.length < 2 ) { + logger.error ( "length of tour participants array is not null, but is < 2; should be >= 2 for joint tour, hhid=" + t.getHhId() + "." ); + throw new RuntimeException(); + } + + data.add(string(participants.length)); + data.add(string(t.getTourModeChoice())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + + data.add(string(s.getBTap())); + data.add(string(s.getATap())); + + data.add(string(tazDataManager.getTazsForMazs()[s.getOrig()-1])); + data.add(string(tazDataManager.getTazsForMazs()[s.getDest()-1])); + + return data; + } + + + private List formTourAsIndivTripDataEntry(TourIf t, boolean inbound) { + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getPersonObject().getPersonId())); + data.add(string(t.getPersonObject().getPersonNum())); + data.add(string(t.getTourId())); + data.add(string( -1 )); + data.add(string((inbound ? 1 : 0))); + data.add(string(t.getTourPrimaryPurpose())); + + if ( inbound ) { + // inbound trip on half-tour with no stops + if ( t.getTourCategoryIsAtWork() ) { + data.add(t.getTourPrimaryPurpose()); + data.add("Work"); + } + else { + data.add(t.getTourPrimaryPurpose()); + data.add("Home"); + } + } + else { + // outbound trip on half-tour with no stops + if ( t.getTourCategoryIsAtWork() ) { + data.add("Work"); + data.add(t.getTourPrimaryPurpose()); + } + else { + data.add("Home"); + data.add(t.getTourPrimaryPurpose()); + } + } + + data.add(string((inbound ? t.getTourDestTaz() : t.getTourOrigTaz()))); + data.add(string((inbound ? t.getTourDestWalkSubzone() : t.getTourOrigWalkSubzone()))); + data.add(string((inbound ? t.getTourOrigTaz() : t.getTourDestTaz()))); + data.add(string((inbound ? t.getTourOrigWalkSubzone() : t.getTourDestWalkSubzone()))); + data.add(string(t.getTourParkTaz())); + data.add(string(inbound ? t.getTourArrivePeriod() : t.getTourDepartPeriod() )); + data.add(string(t.getTourModeChoice())); + data.add(string(t.getTourModeChoice())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + + data.add(string((inbound ? t.getTourBTapIn() : t.getTourBTapOut()))); + data.add(string((inbound ? t.getTourATapIn() : t.getTourATapOut()))); + + data.add(string((inbound ? tazDataManager.getTazsForMazs()[t.getTourDestTaz()-1] : tazDataManager.getTazsForMazs()[t.getTourOrigTaz()-1]))); + data.add(string((inbound ? tazDataManager.getTazsForMazs()[t.getTourOrigTaz()-1] : tazDataManager.getTazsForMazs()[t.getTourDestTaz()-1]))); + + return data; + } + + private List formTourAsJointTripDataEntry(TourIf t, boolean inbound) { + List data = new LinkedList(); + data.add(string(t.getHhId())); + data.add(string(t.getTourId())); + data.add(string( -1 )); + data.add(string((inbound ? 1 : 0))); + data.add(string(t.getTourPrimaryPurpose())); + + if ( inbound ) { + // inbound trip on half-tour with no stops + if ( t.getTourCategoryIsAtWork() ) { + data.add(t.getTourPrimaryPurpose()); + data.add("Work"); + } + else { + data.add(t.getTourPrimaryPurpose()); + data.add("Home"); + } + } + else { + // outbound trip on half-tour with no stops + if ( t.getTourCategoryIsAtWork() ) { + data.add("Work"); + data.add(t.getTourPrimaryPurpose()); + } + else { + data.add("Home"); + data.add(t.getTourPrimaryPurpose()); + } + } + + data.add(string((inbound ? t.getTourDestTaz() : t.getTourOrigTaz()))); + data.add(string((inbound ? t.getTourDestWalkSubzone() : t.getTourOrigWalkSubzone()))); + data.add(string((inbound ? t.getTourOrigTaz() : t.getTourDestTaz()))); + data.add(string((inbound ? t.getTourOrigWalkSubzone() : t.getTourDestWalkSubzone()))); + data.add(string(t.getTourParkTaz())); + data.add(string(inbound ? t.getTourArrivePeriod() : t.getTourDepartPeriod() )); + data.add(string(t.getTourModeChoice())); + + byte[] participants = t.getPersonNumArray(); + if ( participants == null ) { + logger.error ( "tour participants array is null, hhid=" + t.getHhId() + "." ); + throw new RuntimeException(); + } + if ( participants.length < 2 ) { + logger.error ( "length of tour participants array is not null, but is < 2; should be >= 2 for joint tour, hhid=" + t.getHhId() + "." ); + throw new RuntimeException(); + } + + data.add(string(participants.length)); + data.add(string(t.getTourModeChoice())); + data.add(string(ModelStructure.TOUR_CATEGORY_LABELS[t.getTourCategoryIndex()])); + + data.add(string((inbound ? t.getTourBTapIn() : t.getTourATapOut()))); + data.add(string((inbound ? t.getTourBTapIn() : t.getTourATapOut()))); + + data.add(string((inbound ? tazDataManager.getTazsForMazs()[t.getTourDestTaz()-1] : tazDataManager.getTazsForMazs()[t.getTourOrigTaz()-1]))); + data.add(string((inbound ? tazDataManager.getTazsForMazs()[t.getTourOrigTaz()-1] : tazDataManager.getTazsForMazs()[t.getTourDestTaz()-1]))); + + return data; + } + + + private static enum SqliteDataTypes { + INTEGER, + TEXT, + REAL + } + + private interface DataWriter { + void writeHouseholdData(List data); + void writePersonData(List data); + void writeIndivTourData(List data); + void writeJointTourData(List data); + void writeIndivTripData(List data); + void writeJointTripData(List data); + void writeTripData(List entries); + void writeTravelTimeData(int[] zoneList); + void finishActions(); + Boolean getWriteTripFileFlag(); + Boolean getWriteTravelTimesFileFlag(); + } + + private class DatabaseDataWriter implements DataWriter { + private final String householdTable = resourceBundle.getString(PROPERTIES_HOUSEHOLD_TABLE); + private final String personTable = resourceBundle.getString(PROPERTIES_PERSON_TABLE); + private final String indivTourTable = resourceBundle.getString(PROPERTIES_INDIV_TOUR_TABLE); + private final String jointTourTable = resourceBundle.getString(PROPERTIES_JOINT_TOUR_TABLE); + private final String indivTripTable = resourceBundle.getString(PROPERTIES_INDIV_TRIP_TABLE); + private final String jointTripTable = resourceBundle.getString(PROPERTIES_JOINT_TRIP_TABLE); + private Connection connection = null; + private PreparedStatement hhPreparedStatement = null; + private PreparedStatement personPreparedStatement = null; + private PreparedStatement indivTourPreparedStatement = null; + private PreparedStatement jointTourPreparedStatement = null; + private PreparedStatement indivTripPreparedStatement = null; + private PreparedStatement jointTripPreparedStatement = null; + + private Boolean writeTripFileFlag = false; + private Boolean writeTravelTimesFileFlag = false; + + public DatabaseDataWriter( String dbFileName ) { + initializeTables(dbFileName); + } + + private void initializeTables( String dbFileName ) { + Statement s = null; + try { + connection = ConnectionHelper.getConnection(dbFileName); + s = connection.createStatement(); + s.addBatch(getTableInitializationString(householdTable,formHouseholdColumnNames(),formHouseholdColumnTypes())); + s.addBatch(getTableInitializationString(personTable,formPersonColumnNames(),formPersonColumnTypes())); + s.addBatch(getTableInitializationString(indivTourTable,formIndivTourColumnNames(),formIndivTourColumnTypes())); + s.addBatch(getTableInitializationString(jointTourTable,formJointTourColumnNames(),formJointTourColumnTypes())); + s.addBatch(getTableInitializationString(indivTripTable,formIndivTripColumnNames(),formIndivTripColumnTypes())); + s.addBatch(getTableInitializationString(jointTripTable,formJointTripColumnNames(),formJointTripColumnTypes())); + s.addBatch(getClearTableString(householdTable)); + s.addBatch(getClearTableString(personTable)); + s.addBatch(getClearTableString(indivTourTable)); + s.addBatch(getClearTableString(jointTourTable)); + s.addBatch(getClearTableString(indivTripTable)); + s.addBatch(getClearTableString(jointTripTable)); + s.executeBatch(); + } catch (SQLException e) { + try { + if (connection != null) + connection.close(); + } catch (SQLException ee) { + //swallow + } + throw new RuntimeException(e); + } finally { + closeStatement(s); + } + setupPreparedStatements(); + } + + private void setupPreparedStatements() { + String psStart = "INSERT INTO "; + String psMiddle = " VALUES (?"; + StringBuilder hhp = new StringBuilder(psStart); + hhp.append(householdTable).append(psMiddle); + for (int i = 1; i < formHouseholdColumnNames().size(); i++) + hhp.append(",?"); + hhp.append(");"); + StringBuilder pp = new StringBuilder(psStart); + pp.append(personTable).append(psMiddle); + for (int i = 1; i < formPersonColumnNames().size(); i++) + pp.append(",?"); + pp.append(");"); + StringBuilder itp = new StringBuilder(psStart); + itp.append(indivTourTable).append(psMiddle); + for (int i = 1; i < formIndivTourColumnNames().size(); i++) + itp.append(",?"); + itp.append(");"); + StringBuilder jtp = new StringBuilder(psStart); + jtp.append(jointTourTable).append(psMiddle); + for (int i = 1; i < formJointTourColumnNames().size(); i++) + jtp.append(",?"); + jtp.append(");"); + StringBuilder itp2 = new StringBuilder(psStart); + itp2.append(indivTripTable).append(psMiddle); + for (int i = 1; i < formIndivTripColumnNames().size(); i++) + itp2.append(",?"); + itp2.append(");"); + StringBuilder jtp2 = new StringBuilder(psStart); + jtp2.append(jointTripTable).append(psMiddle); + for (int i = 1; i < formJointTripColumnNames().size(); i++) + jtp2.append(",?"); + jtp2.append(");"); + try { + hhPreparedStatement = connection.prepareStatement(hhp.toString()); + personPreparedStatement = connection.prepareStatement(pp.toString()); + indivTourPreparedStatement = connection.prepareStatement(itp.toString()); + jointTourPreparedStatement = connection.prepareStatement(jtp.toString()); + indivTripPreparedStatement = connection.prepareStatement(itp2.toString()); + jointTripPreparedStatement = connection.prepareStatement(jtp2.toString()); + connection.setAutoCommit(false); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private String getTableInitializationString(String table, List columns, List types) { + StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS "); + sb.append(table).append(" ("); + Iterator cols = columns.iterator(); + Iterator tps = types.iterator(); + sb.append(cols.next()).append(" ").append(tps.next().name()); + while (cols.hasNext()) + sb.append(",").append(cols.next()).append(" ").append(tps.next().name()); + sb.append(");"); + return sb.toString(); + } + + private String getClearTableString(String table) { + return "DELETE FROM " + table + ";"; + } + + private void writeToTable(PreparedStatement ps, List values) { + try { + int counter = 1; + for (String value : values) + ps.setString(counter++,value); + ps.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void writeHouseholdData(List data) { + writeToTable(hhPreparedStatement,data); + } + + public void writePersonData(List data) { + writeToTable(personPreparedStatement,data); + } + + public void writeIndivTourData(List data) { + writeToTable(indivTourPreparedStatement,data); + } + + public void writeJointTourData(List data) { + writeToTable(jointTourPreparedStatement,data); + } + + public void writeIndivTripData(List data) { + writeToTable(indivTripPreparedStatement,data); + } + + public void writeJointTripData(List data) { + writeToTable(jointTripPreparedStatement,data); + } + + public void writeTripData(List entries) { + throw new UnsupportedOperationException("Database writer does not support writing trip table."); + } + + public void writeTravelTimeData(int[] zoneList) { + throw new UnsupportedOperationException("Database writer does not support writing travel time table"); + } + + public void finishActions() { + + try { + connection.commit(); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + closeStatement(hhPreparedStatement); + closeStatement(personPreparedStatement); + closeStatement(indivTourPreparedStatement); + closeStatement(jointTourPreparedStatement); + closeStatement(indivTripPreparedStatement); + closeStatement(jointTripPreparedStatement); + try { + if (connection != null) + connection.close(); + } catch (SQLException ee) { + //swallow + } + } + } + + private void closeStatement(Statement s) { + try { + if (s != null) + s.close(); + } catch (SQLException e) { + //swallow + } + } + + public Boolean getWriteTripFileFlag() { + return(writeTripFileFlag); + } + + public Boolean getWriteTravelTimesFileFlag() { + return(writeTravelTimesFileFlag); + } + } + + private void loadTourModes(ResourceBundle properties, CtrampDmuFactoryIf dmuFactory) { + tourModeAltLabels = new HashMap>(); + String mcUecFile = properties.getString(CtrampApplication.PROPERTIES_PROJECT_DIRECTORY) + + properties.getString(com.pb.models.ctrampIf.jppf.ModeChoiceModel.PROPERTIES_UEC_TOUR_MODE_CHOICE); + + String[] categories = {ModelStructure.MANDATORY_CATEGORY,ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY, + ModelStructure.JOINT_NON_MANDATORY_CATEGORY,ModelStructure.AT_WORK_CATEGORY}; + VariableTable vt = dmuFactory.getModeChoiceDMU(); + @SuppressWarnings("unchecked") //this will return a HashMap - signature of method is missing generic declaration + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + + for (String tourCategory : categories) { + // create a HashMap to map purposeName to model index + Map purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + for ( String purposeName : modelStructure.getDcModelPurposeList( tourCategory ) ) { + int uecIndex = modelStructure.getTourModeChoiceUecIndexForPurpose(purposeName); + purposeModelIndexMap.put(purposeName,uecIndex); + modelIndexSet.add( uecIndex ); + } + + for (int m : modelIndexSet) { + String[] altNames = new ChoiceModelApplication(mcUecFile, m,com.pb.models.ctrampIf.jppf.ModeChoiceModel.MC_DATA_SHEET,propertyMap,vt).getAlternativeNames(); + //save mode names by purpose + Map modeNameMap = new HashMap(); + for (int i = 0; i < altNames.length; i++) + modeNameMap.put(i+1,altNames[i]); //mode indices are indexed by 1 + for (String p : purposeModelIndexMap.keySet()) {//more than one purpose may use same index map + if (purposeModelIndexMap.get(p) == m) { + if (!tourModeAltLabels.containsKey(p)) + tourModeAltLabels.put(p,new HashMap()); + tourModeAltLabels.get(p).putAll(modeNameMap); + } + } + } + } + } + + private void loadTripModes(ResourceBundle properties, CtrampDmuFactoryIf dmuFactory) { + tripModeAltLabels = new HashMap>(); + String uecFileName = properties.getString(CtrampApplication.PROPERTIES_PROJECT_DIRECTORY) + + properties.getString(StopLocationModeChoiceModel.PROPERTIES_UEC_TRIP_MODE_CHOICE); + + VariableTable vt = dmuFactory.getTripModeChoiceDMU(); + @SuppressWarnings("unchecked") //this will return a HashMap - signature of method is missing generic declaration + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + + for (int i : modelStructure.getTripModeChoiceModelSheetIndices()) { + //get mode names + Map modeNameMap = new HashMap(); + int counter = 1; //trip modes are indexed by 1 + for (String name : new ChoiceModelApplication(uecFileName,i,StopLocationModeChoiceModel.UEC_DATA_PAGE,propertyMap,vt).getAlternativeNames()) + modeNameMap.put(counter++,name); + if (!tripModeAltLabels.containsKey(i)) + tripModeAltLabels.put(i,new HashMap()); + tripModeAltLabels.get(i).putAll(modeNameMap); + } + } + + private class FileDataWriter implements DataWriter{ + + private final PrintWriter hhWriter; + private final PrintWriter personWriter; + private final PrintWriter indivTourWriter; + private final PrintWriter jointTourWriter; + private final PrintWriter indivTripWriter; + private final PrintWriter jointTripWriter; + private PrintWriter tripWriter; + private PrintWriter travelTimeWriter; + + private Boolean writeTripFileFlag = false; + private Boolean writeTravelTimesFileFlag = false; + + public FileDataWriter() { + String baseDir = ResourceUtil.getProperty(resourceBundle,CtrampApplication.PROPERTIES_PROJECT_DIRECTORY); + + String hhFile = formFileName( resourceBundle.getString(PROPERTIES_HOUSEHOLD_DATA_FILE), iteration ); + String personFile = formFileName( resourceBundle.getString(PROPERTIES_PERSON_DATA_FILE), iteration ); + String indivTourFile = formFileName( resourceBundle.getString(PROPERTIES_INDIV_TOUR_DATA_FILE), iteration ); + String jointTourFile = formFileName( resourceBundle.getString(PROPERTIES_JOINT_TOUR_DATA_FILE), iteration ); + String indivTripFile = formFileName( resourceBundle.getString(PROPERTIES_INDIV_TRIP_DATA_FILE), iteration ); + String jointTripFile = formFileName( resourceBundle.getString(PROPERTIES_JOINT_TRIP_DATA_FILE), iteration ); + + //write trip file and travel times file + String tripFile = ""; + String travelTimeFile = ""; + if ( resourceBundle.containsKey(PROPERTIES_TRIP_DATA_FILE) ) { + tripFile = formFileName(resourceBundle.getString(PROPERTIES_TRIP_DATA_FILE), iteration ); + writeTripFileFlag = true; + } + if ( resourceBundle.containsKey(PROPERTIES_TRAVEL_TIME_DATA_FILE) ) { + travelTimeFile = formFileName(resourceBundle.getString(PROPERTIES_TRAVEL_TIME_DATA_FILE), iteration ); + writeTravelTimesFileFlag = true; + } + + try { + hhWriter = new PrintWriter(new File(baseDir + hhFile)); + personWriter = new PrintWriter(new File(baseDir + personFile)); + indivTourWriter = new PrintWriter(new File(baseDir + indivTourFile)); + jointTourWriter = new PrintWriter(new File(baseDir + jointTourFile)); + indivTripWriter = new PrintWriter(new File(baseDir + indivTripFile)); + jointTripWriter = new PrintWriter(new File(baseDir + jointTripFile)); + if(writeTripFileFlag) { + tripWriter = new PrintWriter(new File(baseDir + tripFile)); + } + if(writeTravelTimesFileFlag) { + travelTimeWriter = new PrintWriter(new File(baseDir + travelTimeFile)); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + writeHouseholdData(formHouseholdColumnNames()); + writePersonData(formPersonColumnNames()); + writeIndivTourData(formIndivTourColumnNames()); + writeJointTourData(formJointTourColumnNames()); + writeIndivTripData(formIndivTripColumnNames()); + writeJointTripData(formJointTripColumnNames()); + if(writeTripFileFlag) { + tripWriter.println(formTripTableColumnHeader()); + } + if(writeTravelTimesFileFlag) { + travelTimeWriter.println(formTravelTimeTableColumnHeader()); + } + + } + + private String formFileName( String originalFileName, int iteration ) { + int lastDot = originalFileName.lastIndexOf('.'); + + String returnString = ""; + if ( lastDot > 0 ) { + String base = originalFileName.substring( 0, lastDot ); + String ext = originalFileName.substring( lastDot ); + returnString = String.format( "%s_%d%s", base, iteration, ext ); + } + else { + returnString = String.format( "%s_%d.csv", originalFileName, iteration ); + } + + logger.info( "writing " + originalFileName + " csv file to " + returnString ); + + return returnString; + } + + public void writeHouseholdData(List data) { + writeEntryToCsv(hhWriter,data); + } + + public void writePersonData(List data) { + writeEntryToCsv(personWriter,data); + } + + public void writeIndivTourData(List data) { + writeEntryToCsv(indivTourWriter,data); + } + + public void writeJointTourData(List data) { + writeEntryToCsv(jointTourWriter,data); + } + + public void writeIndivTripData(List data) { + writeEntryToCsv(indivTripWriter,data); + } + + public void writeJointTripData(List data) { + writeEntryToCsv(jointTripWriter,data); + } + + public void writeTripData(List entries) { + for (String entry : entries) + tripWriter.println(entry); + } + + public void writeTravelTimeData(int[] zoneList) { + for (int origin : zoneList) + for (int dest : zoneList) + for (String line : getTravelTimeTableEntries(origin,dest)) + travelTimeWriter.println(line); + } + + private void writeEntryToCsv(PrintWriter pw, List data) { + pw.println(formCsvString(data)); + } + + private String formCsvString(List data) { + char delimiter = ','; + Iterator it = data.iterator(); + StringBuilder sb = new StringBuilder(it.next()); + while (it.hasNext()) + sb.append(delimiter).append(it.next()); + return sb.toString(); + } + + public void finishActions() { + try { + hhWriter.flush(); + personWriter.flush(); + indivTourWriter.flush(); + jointTourWriter.flush(); + indivTripWriter.flush(); + jointTripWriter.flush(); + if(writeTripFileFlag) { + tripWriter.flush(); + } + if(writeTravelTimesFileFlag) { + travelTimeWriter.flush(); + } + } finally { + hhWriter.close(); + personWriter.close(); + indivTourWriter.close(); + jointTourWriter.close(); + indivTripWriter.close(); + jointTripWriter.close(); + if(writeTripFileFlag) { + tripWriter.close(); + } + if(writeTravelTimesFileFlag) { + travelTimeWriter.close(); + } + } + } + + public Boolean getWriteTripFileFlag() { + return(writeTripFileFlag); + } + + public Boolean getWriteTravelTimesFileFlag() { + return(writeTravelTimesFileFlag); + } + } + + private List getTravelTimeTableEntries(int origin, int dest) { + String travelTimeFormat = resourceBundle.getString(PROPERTIES_TRAVEL_TIME_FORMAT); + List entries = new LinkedList(); + for (String period : travelTimeModel.getTimePeriods()) { + String[] alts = travelTimeModel.getAlternatives(period); + double[] times = travelTimeModel.getTravelTimes(period,origin,dest); + for (int i = 0; i < alts.length; i++) { + entries.add(new StringBuilder() + .append(origin).append(",") + .append(dest).append(",") + .append(period).append(",") + .append(alts[i]).append(",") + .append(String.format(travelTimeFormat,times[i])).toString()); + } + } + return entries; + } + + private List createVizTripRecords(HouseholdIf hh) { + PersonIf[] persons = hh.getPersons(); + List>> personRecords = new ArrayList>>(); + for (PersonIf p : hh.getPersons()) { + if (p == null) { //deal with 1-based arrays + personRecords.add(null); + continue; + } + Map> recordMap = new TreeMap>(); //orders by departure time + personRecords.add(recordMap); + for (TourIf t : p.getListOfWorkTours()) + addTripsFromTour(p,t,recordMap); + for (TourIf t : p.getListOfIndividualNonMandatoryTours()) + addTripsFromTour(p,t,recordMap); + for (TourIf t : p.getListOfSchoolTours()) + addTripsFromTour(p,t,recordMap); + for (TourIf t : p.getListOfAtWorkSubtours()) + addTripsFromTour(p,t,recordMap); + } + + TourIf[] jointTours = hh.getJointTourArray(); + if (jointTours != null) + for (TourIf t : jointTours) + for (byte p : t.getPersonNumArray()) + addTripsFromTour(persons[p],t,personRecords.get(p)); + + List tours = new LinkedList(); + for (Map> personRecord : personRecords) { + if (personRecord == null) + continue; + int startTime = 5; //todo: don't hard code this + int tripId = 1; + for (Integer departTime : personRecord.keySet()) { + for (StringBuilder[] sb : personRecord.get(departTime)) { + tours.add(sb[0].append(tripId++).append(",").append(startTime).append(sb[2]).toString()); //tripId is across persons, not just within tours + startTime = departTime; //last activity ended at same time (except first, which is taken care of) + } + } + } + return tours; + } + + private void addTripsFromTour(PersonIf p, TourIf t, Map> tourList) { + StopIf[] stops = t.getOutboundStops(); + if (stops != null) { + for (StopIf s : stops) { + int h = s.getStopPeriod(); + if (!tourList.containsKey(h)) + tourList.put(h,new LinkedList()); + tourList.get(h).add(getVizTripString(p,s)); + } + } else { + int h = t.getTourDepartPeriod(); + if (!tourList.containsKey(h)) + tourList.put(h,new LinkedList()); + tourList.get(h).add(getVizTripString(p,t,false)); + } + stops = t.getInboundStops(); + if (stops != null) { + for (StopIf s : stops) { + int h = s.getStopPeriod(); + if (!tourList.containsKey(h)) + tourList.put(h,new LinkedList()); + tourList.get(h).add(getVizTripString(p,s)); + } + } else { + int h = t.getTourArrivePeriod(); + if (!tourList.containsKey(h)) + tourList.put(h,new LinkedList()); + tourList.get(h).add(getVizTripString(p,t,false)); + } + } + + private StringBuilder[] getVizTripString(PersonIf p, TourIf t, boolean returnTrip) { + + HouseholdIf hh = p.getHouseholdObject(); + + byte[] persons = t.getPersonNumArray(); + StringBuilder personsSb = new StringBuilder(); + if (persons == null) { + personsSb.append(p.getPersonNum()); + } else { + personsSb.append(persons[0]); + for (int i = 1; i < persons.length; i++) + personsSb.append(" ").append(persons[i]); + } + int diff = hh.getAutoOwnershipModelResult() - hh.getWorkers(); + String suff = diff < 0 ? "cars= 0 ? "cars>=wkrs" : "nocars"; + String tourCategory; + if (t.getTourCategoryIsMandatory()) + tourCategory = ModelStructure.MANDATORY_CATEGORY; + else if (t.getTourCategoryIsIndivNonMandatory()) + tourCategory = ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY; + else if (t.getTourCategoryIsJointNonMandatory()) + tourCategory = ModelStructure.JOINT_NON_MANDATORY_CATEGORY; + else + tourCategory = ModelStructure.AT_WORK_CATEGORY; + String tripMode = tourModeAltLabels.get(t.getTourPrimaryPurpose().toLowerCase()).get(t.getTourModeChoice()); + int departHour = returnTrip ? t.getTourArrivePeriod() : t.getTourDepartPeriod(); + int origin = returnTrip ? t.getTourDestTaz() : t.getTourOrigTaz(); + int dest = returnTrip ? t.getTourOrigTaz() : t.getTourDestTaz(); + + StringBuilder[] record = new StringBuilder[3]; + record[0] = new StringBuilder() + .append(hh.getHhId()).append(",") + .append(p.getPersonId()).append(",") + .append(p.getPersonNum()).append(",") + .append(t.getTourId()).append(",") + .append(-1).append(",") + .append(returnTrip ? 0 : 1).append(",") + .append(tourCategory).append(",") + .append(t.getTourPrimaryPurpose()).append(",") + .append(returnTrip ? t.getTourPrimaryPurpose() : t.getTourCategoryIsAtWork() ? "work" : "home").append(",") + .append(returnTrip ? (t.getTourCategoryIsAtWork() ? "work" : "home") : t.getTourPrimaryPurpose()).append(",") + .append(origin).append(",") + .append(dest).append(",") + .append(returnTrip ? t.getTourDestWalkSubzone() : t.getTourOrigWalkSubzone()).append(",") + .append(returnTrip ? t.getTourOrigWalkSubzone() : t.getTourDestWalkSubzone()).append(",") + .append(returnTrip ? 0 : t.getTourParkTaz()).append(",") + .append(departHour).append(",") + .append(t.getTourModeChoice()).append(",") + .append(t.getTourModeChoice()).append(",") + .append(persons == null ? 1 : persons.length).append(",") + .append(personsSb).append(",") + .append(t.getTourDepartPeriod()).append(",") + .append(tourCategory).append("_").append(t.getTourId()).append("_").append(t.getTourPrimaryPurpose()).append(","); //unique id + record[2] = new StringBuilder() + .append(",") + .append(hh.getHhTaz()).append(",") + .append(hh.getIncomeInDollars()).append(",") + .append(hh.getAutoOwnershipModelResult()).append(",") + .append(p.getFreeParkingAvailableResult()).append(",") + .append(hh.getIncomeSegment()).append(",") + .append(hh.getHhSize()).append(",") + .append(hh.getWorkers()).append(",") + .append(suff).append(",") + .append(p.getAge()).append(",") + .append(p.getGender() == 2 ? "Female" : "Male").append(",") + .append(p.getPersonType()).append(",") + .append(p.getCdapActivity()).append(",") + .append(tourModeAltLabels.get(t.getTourPrimaryPurpose().toLowerCase()).get(t.getTourModeChoice())).append(",") //trip mode name + .append(tripMode).append(",") //tour mode name + .append(tripMode == null ? -1 : travelTimeModel.getTravelTime(tripMode,departHour,origin,dest)); + if (tripMode == null) + logger.info("Null trip mode: " + t.getTourPrimaryPurpose().toLowerCase()+ " " + t.getTourModeChoice()); + return record; + } + + private StringBuilder[] getVizTripString(PersonIf p, StopIf s) { + HouseholdIf hh = p.getHouseholdObject(); + TourIf t = s.getTour(); + + byte[] persons = t.getPersonNumArray(); + StringBuilder personsSb = new StringBuilder(); + if (persons == null) { + personsSb.append(p.getPersonNum()); + } else { + personsSb.append(persons[0]); + for (int i = 1; i < persons.length; i++) + personsSb.append(" ").append(persons[i]); + } + String suff = "nocars"; + if(hh.getAutoOwnershipModelResult() > 0) { + int diff = hh.getAutoOwnershipModelResult() - hh.getWorkers(); + suff = diff < 0 ? "cars=wkrs"; + } + String tourCategory; + if (t.getTourCategoryIsMandatory()) + tourCategory = ModelStructure.MANDATORY_CATEGORY; + else if (t.getTourCategoryIsIndivNonMandatory()) + tourCategory = ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY; + else if (t.getTourCategoryIsJointNonMandatory()) + tourCategory = ModelStructure.JOINT_NON_MANDATORY_CATEGORY; + else + tourCategory = ModelStructure.AT_WORK_CATEGORY; + String tripMode = tripModeAltLabels.get(modelStructure.getTripModeChoiceModelIndex(t.getTourPrimaryPurpose().toLowerCase())).get(s.getMode()); + + StringBuilder[] record = new StringBuilder[3]; + record[0] = new StringBuilder() + .append(hh.getHhId()).append(",") + .append(p.getPersonId()).append(",") + .append(p.getPersonNum()).append(",") + .append(t.getTourId()).append(",") + .append(s.getStopId()).append(",") + .append(s.isInboundStop() ? 1 : 0).append(",") + .append(tourCategory).append(",") + .append(t.getTourPrimaryPurpose()).append(",") + .append(s.getOrigPurpose()).append(",") + .append(s.getDestPurpose()).append(",") + .append(s.getOrig()).append(",") + .append(s.getDest()).append(",") + .append(s.getOrigWalkSegment()).append(",") + .append(s.getDestWalkSegment()).append(",") + .append(s.getPark()).append(",") + .append(s.getStopPeriod()).append(",") + .append(s.getMode()).append(",") + .append(t.getTourModeChoice()).append(",") + .append(persons == null ? 1 : persons.length).append(",") + .append(personsSb).append(",") + .append(t.getTourDepartPeriod()).append(",") + .append(tourCategory).append("_").append(t.getTourId()).append("_").append(t.getTourPrimaryPurpose()).append(","); //unique id + record[2] = new StringBuilder() + .append(",") + .append(hh.getHhTaz()).append(",") + .append(hh.getIncomeInDollars()).append(",") + .append(hh.getAutoOwnershipModelResult()).append(",") + .append(p.getFreeParkingAvailableResult()).append(",") + .append(hh.getIncomeSegment()).append(",") + .append(hh.getHhSize()).append(",") + .append(hh.getWorkers()).append(",") + .append(suff).append(",") + .append(p.getAge()).append(",") + .append(p.getGender() == 2 ? "Female" : "Male").append(",") + .append(p.getPersonType()).append(",") + .append(p.getCdapActivity()).append(",") + .append(tourModeAltLabels.get(t.getTourPrimaryPurpose().toLowerCase()).get(t.getTourModeChoice())).append(",") //trip mode name + .append(tripMode).append(",") //tour mode name + .append(tripMode == null ? -1 : travelTimeModel.getTravelTime(tripMode,s.getStopPeriod(),s.getOrig(),s.getDest())); + if (tripMode == null) + logger.info("Null trip mode: " + t.getTourPrimaryPurpose().toLowerCase()+ " " + s.getMode()); + return record; + } + + + private ArrayList getWriteHouseholdRanges( int numberOfHouseholds ) { + + ArrayList startEndIndexList = new ArrayList(); + + int startIndex = 0; + int endIndex = 0; + + while ( endIndex < numberOfHouseholds - 1 ) { + endIndex = startIndex + NUM_WRITE_PACKETS - 1; + if ( endIndex + NUM_WRITE_PACKETS > numberOfHouseholds ) + endIndex = numberOfHouseholds - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += NUM_WRITE_PACKETS; + } + + + return startEndIndexList; + + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/HouseholdIf.java b/src/java/com/pb/models/ctrampIf/HouseholdIf.java new file mode 100644 index 0000000..0da20fb --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/HouseholdIf.java @@ -0,0 +1,325 @@ +package com.pb.models.ctrampIf; + +import java.util.Random; +import org.apache.log4j.Logger; + + +public interface HouseholdIf +{ + + /** + * + * @return a 1-based array of the person objects in the household + */ + public abstract PersonIf[] getPersons(); + + public abstract void initializeWindows(); + + public abstract void setDebugChoiceModels(boolean value); + + public abstract void setHhId(int id, int baseSeed); + + public abstract void setRandomObject(Random r); + + public abstract void setHhRandomCount(int count); + + // work/school location choice uses shadow pricing, so save randomCount per iteration + public abstract void setUwslRandomCount(int iter, int count); + + public abstract void setAoRandomCount(int count); + + public abstract void setFpRandomCount(int count); + + public abstract void setCdapRandomCount(int count); + + public abstract void setImtfRandomCount(int count); + + public abstract void setImtodRandomCount(int count); + + public abstract void setAwfRandomCount(int count); + + public abstract void setAwlRandomCount(int count); + + public abstract void setAwtodRandomCount(int count); + + public abstract void setJtfRandomCount(int count); + + public abstract void setJtlRandomCount(int count); + + public abstract void setJtodRandomCount(int count); + + public abstract void setInmtfRandomCount(int count); + + public abstract void setInmtlRandomCount(int count); + + public abstract void setInmtodRandomCount(int count); + + public abstract void setStfRandomCount(int count); + + public abstract void setStlRandomCount(int count); + + public abstract void setHhTaz(int taz); + + public abstract void setHhWalkSubzone(int subzone); + + public abstract void setHhAutos(int autos); + + public abstract void setAutoOwnershipModelResult(int aoModelAlternativeChosen); + + public abstract int getAutoOwnershipModelResult(); + + public abstract void setCoordinatedDailyActivityPatternResult(String pattern); + + public abstract String getCoordinatedDailyActivityPattern(); + + public abstract void setJointTourFreqResult(int altIndex, String altName); + + public abstract int getJointTourFreqChosenAlt(); + + public abstract String getJointTourFreqChosenAltName(); + + public abstract void setHhSize(int numPersons); + + public abstract void setHhIncomeInDollars(int dollars); + + public abstract void setHhWorkers(int numWorkers); + + public abstract void setHhType(int type); + + public abstract boolean getDebugChoiceModels(); + + public abstract int getHhSize(); + + public abstract int getNumberOfNonWorkingAdults(); + + public abstract int getIsNonFamilyHousehold(); + + public abstract int getNumStudents(); + + public abstract int getNumberOfChildrenUnder16WithHomeOrNonMandatoryActivity(); + + public abstract void setHhBldgsz(int code); + + public abstract int getHhBldgsz(); + +// /** +// * return the number of workers this household has for the purpose index. +// * @param purposeIndex is the DC purpose index to be compared to the usual school location index saved for this +// * person upon reading synthetic population file. +// * @return num, a value of the number of workers in the household for this purpose index. +// */ +// public abstract int getNumberOfWorkersWithDcPurposeIndex(int purposeIndex); +// +// /** +// * return the number of university students this household has for the purpose index. +// * @param purposeIndex is the DC purpose index to be compared to the usual school location index saved for this +// * person upon reading synthetic population file. +// * @return num, a value of the number of university students in the household for this purpose index. +// */ +// public abstract int getNumberOfUniversityStudentsWithDcPurposeIndex(int purposeIndex); +// +// /** +// * return the number of school age students this household has for the purpose index. +// * @param purposeIndex is the DC purpose index to be compared to the usual school location index saved for this +// * person upon reading synthetic population file. +// * @return num, a value of the number of school age students in the household for this purpose index. +// */ +// public abstract int getNumberOfDrivingAgedStudentsWithDcPurposeIndex(int purposeIndex); +// +// public abstract int getNumberOfNonDrivingAgedStudentsWithDcPurposeIndex(int purposeIndex); + + public abstract PersonIf getPerson(int persNum); + + public abstract int getHhId(); + + public abstract Random getHhRandom(); + + public abstract int getHhRandomCount(); + + public abstract int getUwslRandomCount(int iter); + + public abstract int getAoRandomCount(); + + public abstract int getFpRandomCount(); + + public abstract int getCdapRandomCount(); + + public abstract int getImtfRandomCount(); + + public abstract int getImtodRandomCount(); + + public abstract int getImmcRandomCount(); + + public abstract int getJtfRandomCount(); + + public abstract int getAwfRandomCount(); + + public abstract int getAwlRandomCount(); + + public abstract int getAwtodRandomCount(); + + public abstract int getAwmcRandomCount(); + + public abstract int getJtlRandomCount(); + + public abstract int getJtodRandomCount(); + + public abstract int getJmcRandomCount(); + + public abstract int getInmtfRandomCount(); + + public abstract int getInmtlRandomCount(); + + public abstract int getInmtodRandomCount(); + + public abstract int getInmmcRandomCount(); + + public abstract int getStfRandomCount(); + + public abstract int getStlRandomCount(); + + public abstract int getHhTaz(); + + public abstract int getHhWalkSubzone(); + + //TODO suggest getting rid of hhIncome groupings, or moving them down to the project level. + //these vary for different regions, and it can be a source of error to use it here. + //the values here are for ARC only. + public abstract int getIncomeSegment(); + + public abstract int getIncomeInDollars(); + + public abstract int getWorkers(); + + public abstract int getDrivers(); + + public abstract int getSize(); + + public abstract int getChildunder16(); + + public abstract int getChild16plus(); + + public abstract int getNumChildrenUnder16(); + + public abstract int getNumChildren(); + + public abstract int getNumChildrenUnder19(); + + public abstract int getNumPersons0to4(); + + public abstract int getNumPersons5to15(); + + public abstract int getNumPersons6to15(); + + public abstract int getNumPersons16to17(); + + public abstract int getNumPersons16plus(); + + public abstract int getNumPersons18to24(); + + public abstract int getNumPersons65to79(); + + public abstract int getNumPersons80plus(); + + public abstract int getNumFtWorkers(); + + public abstract int getNumPtWorkers(); + + public abstract int getNumUnivStudents(); + + public abstract int getNumNonWorkAdults(); + + public abstract int getNumRetired(); + + public abstract int getNumDrivingStudents(); + + public abstract int getNumNonDrivingStudents(); + + public abstract int getNumPreschool(); + + public abstract int getHighestEducationAttainment(); + + + public void calculateTimeWindowOverlaps(); + + /** + * joint tour frequency choice is not applied to a household unless it has: + * 2 or more persons, each with at least one out-of home activity, and at least 1 of the persons not a pre-schooler. + * */ + public abstract int getValidHouseholdForJointTourFrequencyModel(); + + /** + * return maximum hours of overlap between this person and other adult persons in the household. + * @return the most number of hours mutually available between this person and other adult household members + */ + public abstract int getMaxAdultOverlaps(); + + /** + * return maximum hours of overlap between this person and other children in the household. + * @return the most number of hours mutually available between this person and other child household members + */ + public abstract int getMaxChildOverlaps(); + + /** + * determine maximum number of time consecutive time intervals available to everyone in joint party. + * @param t, the joint tour + * @return maximunm joint continous time window + */ + public abstract int getMaxJointTimeWindow( TourIf t ); + + /** + * return maximum hours of overlap between this person(adult/child) and other persons(child/adult) in the household. + * @return the most number of hours mutually available between this person and other type household members + */ + public abstract int getMaxAdultChildOverlaps(); + + /** + * @return number of adults in household with "M" or "N" activity pattern - that is, traveling adults. + */ + public abstract int getTravelActiveAdults(); + + /** + * @return number of children in household with "M" or "N" activity pattern - that is, traveling children. + */ + public abstract int getTravelActiveChildren(); + + + public abstract boolean[] getAvailableJointTourTimeWindows(TourIf t, int[] altStarts, int[] altEnds); + + public abstract void scheduleJointTourTimeWindows(TourIf t, int start, int end); + + + public abstract void createJointTourArray(); + + public abstract void createJointTourArray(Object[] t1Data); + + public abstract void createJointTourArray(Object[] t1Data, Object[] t2Data); + + public abstract TourIf[] getJointTourArray(); + + public abstract void initializeForAoRestart(); + + public abstract void initializeForImtfRestart(); + + public abstract void initializeForJtfRestart(); + + public abstract void initializeForInmtfRestart(); + + public abstract void initializeForAwfRestart(); + + public abstract void initializeForStfRestart(); + + public abstract void logHouseholdObject(String titleString, Logger logger); + + public abstract void logPersonObject(String titleString, Logger logger, PersonIf person); + + public abstract void logTourObject(String titleString, Logger logger, PersonIf person, TourIf tour); + + public abstract void logStopObject(String titleString, Logger logger, StopIf stop, + ModelStructure modelStructure); + + public abstract long getHouseholdObjectSize(); + + public abstract PersonIf getOldestPerson(); + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/IndividualMandatoryTourFrequencyDMU.java b/src/java/com/pb/models/ctrampIf/IndividualMandatoryTourFrequencyDMU.java new file mode 100644 index 0000000..5122295 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/IndividualMandatoryTourFrequencyDMU.java @@ -0,0 +1,192 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +public class IndividualMandatoryTourFrequencyDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(IndividualMandatoryTourFrequencyDMU.class); + + protected HashMap methodIndexMap; + + protected IndexValues dmuIndex; + protected HouseholdIf household; + protected PersonIf person; + + protected double walkDistanceToWork, walkDistanceToSchool; + protected double roundTripAutoTimeToWork, roundTripAutoTimeToSchool; + + private int homeTazAreaType; + + + public IndividualMandatoryTourFrequencyDMU(){ + dmuIndex = new IndexValues(); + } + + public IndexValues getIndexValues(){ + return dmuIndex; + } + + public void setHousehold(HouseholdIf passedInHousehold){ + household = passedInHousehold; + + // set the origin and zone indices + dmuIndex.setOriginZone(household.getHhTaz()); + dmuIndex.setZoneIndex(household.getHhTaz()); + dmuIndex.setHHIndex(household.getHhId()); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( household.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug IMTF UEC" ); + } + + } + + + public void setHomeTazAreaType( int at ) { + homeTazAreaType = at; + } + + public void setDestinationZone(int destinationZone){ + dmuIndex.setDestZone(destinationZone); + } + + public void setPerson(PersonIf passedInPerson){ + person = passedInPerson; + } + + + + public int getFullTimeWorker(){ + return(person.getPersonTypeIsFullTimeWorker()); + } + + public int getPartTimeWorker(){ + return(person.getPersonTypeIsPartTimeWorker()); + } + + public int getUniversityStudent(){ + return(person.getPersonIsUniversityStudent()); + } + + public int getNonWorkingAdult(){ + return(person.getPersonIsNonWorkingAdultUnder65()); + } + + public int getRetired(){ + return(person.getPersonIsNonWorkingAdultOver65()); + } + + public int getDrivingAgeSchoolChild(){ + return(person.getPersonIsStudentDriving()); + } + + public int getPreDrivingAgeSchoolChild(){ + return(person.getPersonIsStudentNonDriving()); + } + + public int getFemale(){ + return(person.getPersonIsFemale()); + } + + public int getAge(){ + return(person.getAge()); + } + + public int getStudentIsEmployed(){ + + if(person.getPersonIsUniversityStudent()==1 || person.getPersonIsStudentDriving()==1){ + return(person.getPersonIsWorker()); + } + + return (0); + } + + public int getNonStudentGoesToSchool(){ + + if(person.getPersonTypeIsFullTimeWorker()==1 || person.getPersonTypeIsPartTimeWorker()==1 || + person.getPersonIsNonWorkingAdultUnder65()==1 || person.getPersonIsNonWorkingAdultOver65()==1){ + + return(person.getPersonIsStudent()); + } + + return(0); + + + } + + public int getAutos(){ + return (household.getAutoOwnershipModelResult()); + } + + public int getDrivers(){ + return (household.getDrivers()); + } + + public int getPreschoolChildren(){ + return household.getNumPreschool(); + } + + public int getNonWorkers(){ + return (household.getNumberOfNonWorkingAdults()); + } + + public int getNonFamilyHousehold(){ + return(household.getIsNonFamilyHousehold()); + } + + public int getChildrenUnder16NotAtSchool(){ + return(household.getNumberOfChildrenUnder16WithHomeOrNonMandatoryActivity()); + } + + public int getAreaType(){ + return homeTazAreaType; + } + + public int getUsualWorkLocation(){ + return person.getUsualWorkLocation(); + } + + public int getUsualSchoolLocation(){ + return person.getUsualSchoolLocation(); + } + + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/IndividualNonMandatoryTourFrequencyDMU.java b/src/java/com/pb/models/ctrampIf/IndividualNonMandatoryTourFrequencyDMU.java new file mode 100644 index 0000000..aafce1a --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/IndividualNonMandatoryTourFrequencyDMU.java @@ -0,0 +1,555 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + + +public class IndividualNonMandatoryTourFrequencyDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(IndividualNonMandatoryTourFrequencyDMU.class); + + protected HashMap methodIndexMap; + + protected HouseholdIf hh; + protected PersonIf person; + protected IndexValues dmuIndex; + + protected int homeTazIsUrban; + + + public IndividualNonMandatoryTourFrequencyDMU(){ + dmuIndex = new IndexValues(); + } + + + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setPersonObject ( PersonIf persObject ) { + person = persObject; + } + + + + + // DMU methods - define one of these for every @var in the mode choice control file. + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug INMTF UEC" ); + } + + } + + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + /** + * @return household income in dollars + */ + public int getIncomeInDollars() { + return hh.getIncomeInDollars(); + } + + + /** + * @return the number of persons in the "decision making" household. + */ + public int getHouseholdSize() { + // 1-based indexing, so the array is dimensioned 1 more than the number of persons. + return hh.getPersons().length - 1; + } + + + public int getNumAutos() { + return hh.getAutoOwnershipModelResult(); + } + + + /** + * @return 1 if household has at least 1 car, and the number of cars equals the number of workers + */ + public int getCarsEqualsWorkers() { + int numAutos = hh.getAutoOwnershipModelResult(); + int numWorkers = hh.getWorkers(); + + // household must have at least 1 car, otherwise return 0. + if ( numAutos > 0 ) { + // if at least one car and numWorkers == numAutos, return 1, otherwise 0. + if ( numAutos == numWorkers ) + return 1; + else + return 0; + } + else { + return 0; + } + } + + + /** + * @return 1 if household has at least 1 car, and the number of cars equals the number of workers + */ + public int getMoreCarsThanWorkers() { + int numAutos = hh.getAutoOwnershipModelResult(); + int numWorkers = hh.getWorkers(); + + if ( numAutos > numWorkers ) + return 1; + else + return 0; + } + + + public int getNumAdults() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for ( int i=1; i < persons.length; i++ ) + num += persons[i].getPersonIsAdult(); + return num; + } + + public int getNumChildren() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for ( int i=1; i < persons.length; i++ ) + num += ( persons[i].getPersonIsAdult() == 0 ? 1 : 0 ); + return num; + } + + public int getPersonIsAdult() { + return person.getPersonIsAdult(); + } + + public int getPersonIsChild() { + return person.getPersonIsAdult() == 0 ? 1 : 0; + } + + public int getPersonIsFullTimeWorker() { + return person.getPersonIsFullTimeWorker(); + } + + public int getPersonIsPartTimeWorker() { + return person.getPersonIsPartTimeWorker(); + } + + public int getPersonIsUniversity() { + return person.getPersonIsUniversityStudent(); + } + + public int getPersonIsNonworker() { + return person.getPersonIsNonWorkingAdultUnder65() + person.getPersonIsNonWorkingAdultOver65(); + } + + public int getPersonIsPreschool() { + return person.getPersonIsPreschoolChild(); + } + + public int getPersonIsStudentNonDriving() { + return person.getPersonIsStudentNonDriving(); + } + + public int getPersonIsStudentDriving() { + return person.getPersonIsStudentDriving(); + } + + public int getPersonStaysHome() { + return person.getCdapActivity().equalsIgnoreCase("H") ? 1 : 0; + } + + + public int getFemale() { + return person.getPersonIsFemale(); + } + + + /** + * determines the number of persons in the "decision making" household of type: full-time worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of full-time workers. + */ + public int getFullTimeWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: full time worker; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsFullTimeWorker(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: part-time worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of part-time workers. + */ + public int getPartTimeWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: part-time worker; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsPartTimeWorker(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: university student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of university students. + */ + public int getUniversityStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: university student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsUniversityStudent(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: non-worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of non-workers. + */ + public int getNonWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: nonworker + retired; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsNonWorkingAdultUnder65() + p[i].getPersonIsNonWorkingAdultOver65(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: driving-age student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of driving-age students. + */ + public int getDrivingAgeStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: driving-age student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsStudentDriving(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: non-driving-age student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of non-driving-age students. + */ + public int getNonDrivingAgeStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: non-driving-age student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsStudentNonDriving(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: pre-school age. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of pre-school age children. + */ + public int getPreSchoolers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: pre-school; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsPreschoolChild(); + if ( count == 3 ) + break; + } + + return count; + } + + + /** + * set the indicater value for whether the home zone is in an urban area or not. + * this get's determined in the method that determines joint tour frequency and has access to a + * zonal data object, and that code calls this method to set the value for use by the UEC. + * @param urban home zone indicater value + */ + public void setHomeTazIsUrban( int urban ){ + homeTazIsUrban = urban; + } + + /** + * called by methods invoked by UEC.solve() + * @return 1 if residential zone is in urban area, 0 otherwise + */ + public int getHomeTazIsUrban() { + return homeTazIsUrban; + } + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs of adults in household + */ + public int getMaxAdultOverlaps() { + return hh.getMaxAdultOverlaps(); + } + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs of children in household + */ + public int getMaxChildOverlaps() { + return hh.getMaxChildOverlaps(); + } + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs or adults/children where pairs consist of different types in household + */ + public int getMaxMixedOverlaps() { + return hh.getMaxAdultChildOverlaps(); + } + + + + public int getMaxPairwiseOverlapAdult() { + int maxOverlap = 0; + + // get array of person objects for the decision making household + PersonIf[] dmuPersons = hh.getPersons(); + + for ( int i=1; i < dmuPersons.length; i++ ) { + if ( dmuPersons[i].getPersonIsAdult() == 1 ) { + int overlap = getOverlap( person, dmuPersons[i] ); + if ( overlap > maxOverlap ) + maxOverlap = overlap; + } + } + + return maxOverlap; + } + + + public int getMaxPairwiseOverlapChild() { + int maxOverlap = 0; + + // get array of person objects for the decision making household + PersonIf[] dmuPersons = hh.getPersons(); + + for ( int i=1; i < dmuPersons.length; i++ ) { + if ( dmuPersons[i].getPersonIsAdult() == 0 ) { + int overlap = getOverlap( person, dmuPersons[i] ); + if ( overlap > maxOverlap ) + maxOverlap = overlap; + } + } + + return maxOverlap; + } + + + //TODO: find out if this is suposed to be total pairwise available hours, or largest consecutive hours available for persons. + //TODO: right now, assuming total pairwise available hours + private int getOverlap ( PersonIf dmuPerson, PersonIf otherPerson ) { + byte[] dmuWindow = dmuPerson.getTimeWindows(); + byte[] otherWindow = otherPerson.getTimeWindows(); + + int overlap = 0; + for ( int i=0; i < dmuWindow.length; i++ ){ + if ( dmuWindow[i] == 0 && otherWindow[i] == 0 ) + overlap++; + } + + return overlap; + } + + + + public int getWindowBeforeFirstMandJointTour() { + return person.getWindowBeforeFirstMandJointTour(); + } + + public int getWindowBetweenFirstLastMandJointTour() { + return person.getWindowBetweenFirstLastMandJointTour(); + } + + public int getWindowAfterLastMandJointTour() { + return person.getWindowAfterLastMandJointTour(); + } + + + + + public int getNumHhFtWorkers() { + return hh.getNumFtWorkers(); + } + + public int getNumHhPtWorkers() { + return hh.getNumPtWorkers(); + } + + public int getNumHhUnivStudents() { + return hh.getNumUnivStudents(); + } + + public int getNumHhNonWorkAdults() { + return hh.getNumNonWorkAdults(); + } + + public int getNumHhRetired() { + return hh.getNumRetired(); + } + + public int getNumHhDrivingStudents() { + return hh.getNumDrivingStudents(); + } + + public int getNumHhNonDrivingStudents() { + return hh.getNumNonDrivingStudents(); + } + + public int getNumHhPreschool() { + return hh.getNumPreschool(); + } + + + public int getTravelActiveAdults () { + return hh.getTravelActiveAdults(); + } + + public int getTravelActiveChildren () { + return hh.getTravelActiveChildren(); + } + + public int getNumMandatoryTours() { + return person.getNumMandatoryTours(); + } + + public int getNumJointShoppingTours() { + return person.getNumJointShoppingTours(); + } + + public int getNumJointOthMaintTours() { + return person.getNumJointOthMaintTours(); + } + + public int getNumJointEatOutTours() { + return person.getNumJointEatOutTours(); + } + + public int getNumJointSocialTours() { + return person.getNumJointSocialTours(); + } + + public int getNumJointOthDiscrTours() { + return person.getNumJointOthDiscrTours(); + } + + public int getJTours() { + return hh.getJointTourArray().length; + } + + + + public int getPreDrivingAtHome() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for (int i=1; i < persons.length; i++) { + if ( persons[i].getPersonIsStudentNonDriving() == 1 && persons[i].getCdapActivity().equalsIgnoreCase( CoordinatedDailyActivityPatternModel.HOME_PATTERN ) ) + num++; + } + return num; + } + + public int getPreschoolAtHome() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for (int i=1; i < persons.length; i++) { + if ( persons[i].getPersonIsPreschoolChild() == 1 && persons[i].getCdapActivity().equalsIgnoreCase( CoordinatedDailyActivityPatternModel.HOME_PATTERN ) ) + num++; + } + return num; + } + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/JointTourFrequencyDMU.java b/src/java/com/pb/models/ctrampIf/JointTourFrequencyDMU.java new file mode 100644 index 0000000..1546fa8 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/JointTourFrequencyDMU.java @@ -0,0 +1,636 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + + +public class JointTourFrequencyDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(TourModeChoiceDMU.class); + + protected HashMap methodIndexMap; + + protected HouseholdIf hh; + protected TourIf tour; + protected IndexValues dmuIndex; + private float walkRetailAccessibility = 0.0f; + protected ModelStructure modelStructure; + + protected int homeTazIsUrban; + protected int homeTazIsSuburban; + + public JointTourFrequencyDMU( ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + } + + + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setTourObject ( TourIf tourObject ) { + tour = tourObject; + } + + + + + // DMU methods - define one of these for every @var in the mode choice control file. + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug JTF UEC" ); + } + + } + + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + public void setIndexDest( int d ) { + dmuIndex.setDestZone( d ); + } + + public int getStayHomePatternCountFullTime() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsFullTimeWorker() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getStayHomePatternCountPartTime() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsPartTimeWorker() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getStayHomePatternCountHomemaker() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsNonWorkingAdultUnder65() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getStayHomePatternCountRetiree() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsNonWorkingAdultOver65() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getStayHomePatternCountUnivDrivingStudent() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && (p.getPersonIsUniversityStudent() == 1 || p.getPersonIsStudentDriving() == 1)) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getStayHomePatternCountNonDrivingChild() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && (p.getPersonIsStudentNonDriving() == 1 || p.getPersonIsPreschoolChild() == 1)) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.HOME_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountFullTime() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsFullTimeWorker() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountPartTime() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsPartTimeWorker() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountHomemaker() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsNonWorkingAdultUnder65() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountRetiree() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsNonWorkingAdultOver65() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountUnivDrivingStudent() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && (p.getPersonIsUniversityStudent() == 1 || p.getPersonIsStudentDriving() == 1)) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getNonMandatoryPatternCountNonDrivingChild() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && (p.getPersonIsStudentNonDriving() == 1 || p.getPersonIsPreschoolChild() == 1)) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.NONMANDATORY_PATTERN)) + count ++; + return count; + } + + public int getMandatoryPatternCountFullTime() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsFullTimeWorker() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.MANDATORY_PATTERN)) + count ++; + return count; + } + + public int getMandatoryPatternCountDrivingStudent() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && p.getPersonIsStudentDriving() == 1) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.MANDATORY_PATTERN)) + count ++; + return count; + } + + public int getMandatoryPatternCountNonDrivingChild() { + int count = 0; + for (PersonIf p : hh.getPersons()) + if (p != null && (p.getPersonIsStudentNonDriving() == 1 || p.getPersonIsPreschoolChild() == 1)) + if (p.getCdapActivity().equalsIgnoreCase(CoordinatedDailyActivityPatternModel.MANDATORY_PATTERN)) + count ++; + return count; + } + + public float getTimeWindowOverlapAdult() { + return hh.getMaxAdultOverlaps(); + } + + public float getTimeWindowOverlapChild() { + return hh.getMaxChildOverlaps(); + } + + public float getTimeWindowOverlapAdultChild() { + return hh.getMaxAdultChildOverlaps(); + } + + public int getIncomeBetween50And100() { + int income = hh.getIncomeInDollars(); + return (income > 50000 && income <= 100000) ? 1 : 0; + } + + public int getIncomeGreaterThan100() { + return hh.getIncomeInDollars() > 100000 ? 1 : 0; + } + + public int getAutosInHH() { + return hh.getAutoOwnershipModelResult(); + } + + public int getDriverCount() { + return hh.getDrivers(); + } + + public int getWorkerCount() { + return hh.getWorkers(); + } + + + public void setWalkRetailAccessibility(float walkRetailAccessibility) { + this.walkRetailAccessibility = walkRetailAccessibility; + } + + public float getWalkRetailAccessibility() { + return walkRetailAccessibility; + } + + + + + + + /**************original dmu methods************************/ + + /** + * @return the number of persons in the "decision making" household. + */ + public int getHouseholdSize() { + // 1-based indexing, so the array is dimensioned 1 more than the number of persons. + return hh.getPersons().length - 1; + } + + + /** + * @return 1 if household has at least 1 car, and the number of cars equals the number of workers + */ + public int getCarsEqualsWorkers() { + int numAutos = hh.getAutoOwnershipModelResult(); + int numWorkers = hh.getWorkers(); + + // household must have at least 1 car, otherwise return 0. + if ( numAutos > 0 ) { + // if at least one car and numWorkers == numAutos, return 1, otherwise 0. + if ( numAutos == numWorkers ) + return 1; + else + return 0; + } + else { + return 0; + } + } + + + /** + * @return 1 if household has at least 1 car, and the number of cars equals the number of workers + */ + public int getMoreCarsThanWorkers() { + int numAutos = hh.getAutoOwnershipModelResult(); + int numWorkers = hh.getWorkers(); + + if ( numAutos > numWorkers ) + return 1; + else + return 0; + } + + + public int getNumAdults() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for ( int i=1; i < persons.length; i++ ) + num += persons[i].getPersonIsAdult(); + return num; + } + + public int getNumChildren() { + int num = 0; + PersonIf[] persons = hh.getPersons(); + for ( int i=1; i < persons.length; i++ ) + num += ( persons[i].getPersonIsAdult() == 0 ? 1 : 0 ); + return num; + } + + public int getPersonIsAdult() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsAdult(); + } + + public int getPersonIsChild() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsAdult() == 0 ? 1 : 0; + } + + public int getPersonIsFullTimeWorker() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsFullTimeWorker(); + } + + public int getPersonIsPartTimeWorker() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsPartTimeWorker(); + } + + public int getPersonIsUniversity() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsUniversityStudent(); + } + + public int getPersonIsNonworker() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsNonWorkingAdultUnder65() + p.getPersonIsNonWorkingAdultOver65(); + } + + public int getPersonIsPreschool() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsPreschoolChild(); + } + + public int getPersonIsStudentNonDriving() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsStudentNonDriving(); + } + + public int getPersonIsStudentDriving() { + PersonIf p = tour.getPersonObject(); + return p.getPersonIsStudentDriving(); + } + + public int getPersonStaysHome() { + PersonIf p = tour.getPersonObject(); + return p.getCdapActivity().equalsIgnoreCase("H") ? 1 : 0; + } + + + /** + * determines the number of persons in the "decision making" household of type: full-time worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of full-time workers. + */ + public int getFullTimeWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: full time worker; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsFullTimeWorker(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: part-time worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of part-time workers. + */ + public int getPartTimeWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: part-time worker; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsPartTimeWorker(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: university student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of university students. + */ + public int getUniversityStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: university student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsUniversityStudent(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: non-worker. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of non-workers. + */ + public int getNonWorkers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: nonworker + retired; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsNonWorkingAdultUnder65() + p[i].getPersonIsNonWorkingAdultOver65(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: driving-age student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of driving-age students. + */ + public int getDrivingAgeStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: driving-age student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsStudentDriving(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: non-driving-age student. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of non-driving-age students. + */ + public int getNonDrivingAgeStudents() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: non-driving-age student; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsStudentNonDriving(); + if ( count == 3 ) + break; + } + + return count; + } + + /** + * determines the number of persons in the "decision making" household of type: pre-school age. + * returns the count, or 3, if count is 3 or more. + * @return count (up to a max of 3) of the number of pre-school age children. + */ + public int getPreSchoolers() { + PersonIf[] p = hh.getPersons(); + + // get the count of persons of type: pre-school; if more than 3, return 3. + int count = 0; + for (int i=1; i < p.length; i++) { + count += p[i].getPersonIsPreschoolChild(); + if ( count == 3 ) + break; + } + + return count; + } + + + /** + * set the indicater value for whether the home zone is in an urban area or not. + * this get's determined in the method that determines joint tour frequency and has access to a + * zonal data object, and that code calls this method to set the value for use by the UEC. + * @param urban home zone indicater value + */ + public void setHomeTazIsUrban( int urban ){ + homeTazIsUrban = urban; + } + + /** + * called by methods invoked by UEC.solve() + * @return 1 if residential zone is in urban area, 0 otherwise + */ + public int getHomeTazIsUrban() { + return homeTazIsUrban; + } + + /** + * set the indicater value for whether the home zone is in a suburban area or not. + * this get's determined in the method that determines joint tour frequency and has access to a + * zonal data object, and that code calls this method to set the value for use by the UEC. + * @param suburban home zone indicater value + */ + public void setHomeTazIsSuburban( int suburban ){ + homeTazIsSuburban = suburban; + } + + /** + * called by methods invoked by UEC.solve() + * @return 1 if residential zone is in suburban area, 0 otherwise + */ + public int getHomeTazIsSuburban() { + return homeTazIsSuburban; + } + + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs of adults in household + */ + public int getMaxAdultOverlaps() { + return hh.getMaxAdultOverlaps(); + } + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs of children in household + */ + public int getMaxChildOverlaps() { + return hh.getMaxChildOverlaps(); + } + + /** + * called by methods invoked by UEC.solve() + * @return maximum number of hours mutually available between pairs or adults/children where pairs consist of different types in household + */ + public int getMaxMixedOverlaps() { + return hh.getMaxAdultChildOverlaps(); + } + + public int getMaxPairwiseOverlapAdult() { + return hh.getMaxAdultOverlaps(); + } + + + public int getMaxPairwiseOverlapChild() { + return hh.getMaxChildOverlaps(); + } + + + public int getTravelActiveAdults () { + return hh.getTravelActiveAdults(); + } + + public int getTravelActiveChildren () { + return hh.getTravelActiveChildren(); + } + + public int getTourPurposeIsEat () { + return tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.EAT_OUT_PURPOSE_NAME ) ? 1 : 0; + } + + public int getTourPurposeIsDiscretionary () { + return tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.OTH_DISCR_PURPOSE_NAME ) ? 1 : 0; + } + + public int getJointTourComposition() { + return tour.getJointTourComposition(); + } + + public int getJointTourPurposeIndex() { + return tour.getTourPrimaryPurposeIndex(); + } + + public int getJTours() { + return hh.getJointTourArray().length; + } + + + + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/JointTourFrequencyModel.java b/src/java/com/pb/models/ctrampIf/JointTourFrequencyModel.java new file mode 100644 index 0000000..82d9fea --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/JointTourFrequencyModel.java @@ -0,0 +1,611 @@ +package com.pb.models.ctrampIf; + +import org.apache.log4j.Logger; + +import java.util.*; + +import com.pb.common.newmodel.ChoiceModelApplication; +import com.pb.common.util.ResourceUtil; +import com.pb.common.calculator.IndexValues; + +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 11, 2008 + * Time: 9:25:30 AM + * To change this template use File | Settings | File Templates. + */ +public class JointTourFrequencyModel { + + + protected static Logger logger = Logger.getLogger( JointTourFrequencyModel.class ); + + + public static final String PROPERTIES_UEC_JOINT_TOUR_FREQUENCY = "UecFile.JointTourFrequency"; + + + // all the other page numbers are passed in + public static final int UEC_DATA_PAGE = 0; + public static final int UEC_JOINT_TOUR_FREQ_MODEL_PAGE = 1; + public static final int UEC_JOINT_TOUR_COMPOSITION_MODEL_PAGE = 2; + public static final int UEC_JOINT_TOUR_PARTICIPATION_MODEL_PAGE = 3; + + public static final int JOINT_TOUR_COMPOSITION_ADULTS = 1; + public static final int JOINT_TOUR_COMPOSITION_CHILDREN = 2; + public static final int JOINT_TOUR_COMPOSITION_MIXED = 3; + + public static String[] JOINT_TOUR_COMPOSITION_NAMES = { "", "adult", "child", "mixed" }; + + // DMU for the UEC + protected JointTourFrequencyDMU dmuObject; + + // model structure to compare the .properties time of day with the UECs + protected ModelStructure modelStructure; + protected TazDataIf tazDataManager; + + protected ChoiceModelApplication jointTourFrequencyModel; + protected ChoiceModelApplication jointTourComposition; + protected ChoiceModelApplication jointTourParticipation; + + protected int[][] jointTourChoiceFreq; + protected int[] invalidCount = new int[5]; + + boolean[] participationAvailability; + int[] participationSample; + + TreeMap partySizeFreq = new TreeMap(); + + private String shoppingPurposeString; + private String eatOutPurposeString; + private String maintPurposeString; + private String discrPurposeString; + private String socialPurposeString; + + private int shoppingPurposeIndex; + private int eatOutPurposeIndex; + private int maintPurposeIndex; + private int discrPurposeIndex; + private int socialPurposeIndex; + + + public JointTourFrequencyModel( String projectDirectory, JointTourFrequencyDMU dmu, ModelStructure modelStructure, TazDataIf tazDataManager ){ + + dmuObject = dmu; + + // set the model structure + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + shoppingPurposeString = modelStructure.getShoppingPurposeName(); + shoppingPurposeIndex = modelStructure.getDcModelPurposeIndex( shoppingPurposeString ); + eatOutPurposeString = modelStructure.getEatOutPurposeName(); + eatOutPurposeIndex = modelStructure.getDcModelPurposeIndex( eatOutPurposeString ); + maintPurposeString = modelStructure.getOthMaintPurposeName(); + maintPurposeIndex = modelStructure.getDcModelPurposeIndex( maintPurposeString ); + discrPurposeString = modelStructure.getOthDiscrPurposeName(); + discrPurposeIndex = modelStructure.getDcModelPurposeIndex( discrPurposeString ); + socialPurposeString = modelStructure.getSocialPurposeName(); + socialPurposeIndex = modelStructure.getSoaUecIndexForPurpose(socialPurposeString); + + } + + + public void setUpModels( ResourceBundle resourceBundle, String projectDirectory ){ + + String uecFileName = resourceBundle.getString( PROPERTIES_UEC_JOINT_TOUR_FREQUENCY ); + uecFileName = projectDirectory + uecFileName; + + + // set up the models + jointTourFrequencyModel = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_FREQ_MODEL_PAGE, UEC_DATA_PAGE, + ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle), dmuObject.getClass()); + + jointTourComposition = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_COMPOSITION_MODEL_PAGE, UEC_DATA_PAGE, + ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle), dmuObject.getClass()); + + jointTourParticipation = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_PARTICIPATION_MODEL_PAGE, UEC_DATA_PAGE, + ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle), dmuObject.getClass()); + int numAlts = jointTourParticipation.getNumberOfAlternatives(); + participationAvailability = new boolean[numAlts+1]; + Arrays.fill( participationAvailability, true ); + participationSample = new int[numAlts+1]; + Arrays.fill( participationSample, 1 ); + + + jointTourChoiceFreq = new int[jointTourFrequencyModel.getNumberOfAlternatives()+1][jointTourComposition.getNumberOfAlternatives()+1]; + + } + + + public void applyModel(HouseholdDataManagerIf householdDataManager){ + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray(); + + int tenPercent = (int)( 0.10*householdArray.length ); + + // loop through households (1-based array) + for(int i=1;i 0 ) { + chosenFreqAlt = jointTourFrequencyModel.getChoiceResult( rn ); + household.setJointTourFreqResult( chosenFreqAlt, jointTourFrequencyModel.getAlternativeNames()[chosenFreqAlt-1] ); + } + else { + logger.error ( String.format( "Exception caught for HHID=%d, no available joint tour frequency alternatives to choose from in choiceModelApplication.", household.getHhId() ) ); + throw new RuntimeException(); + } + + + createJointTours ( household, chosenFreqAlt ); + + // can skip composition choice if chosen alt is 1 -- no joint tours; just count the number of times alt 1 is chosen + // in tour frequency. + if ( chosenFreqAlt == 1 ) { + + jointTourChoiceFreq[0][0]++; + + } + else { + + TourIf[] jointTours = household.getJointTourArray(); + for ( int i=0; i < jointTours.length; i++ ) { + + dmuObject.setTourObject( jointTours[i] ); + + jointTourComposition.computeUtilities ( dmuObject, index, availability, sample ); + + hhRandom = household.getHhRandom(); + rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosenComposition = -1; + if ( jointTourComposition.getAvailabilityCount() > 0 ) + chosenComposition = jointTourComposition.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, joint tour i=%d, no available joint tour composition alternatives to choose from in choiceModelApplication.", household.getHhId(), i ) ); + throw new RuntimeException(); + } + + + + jointTours[i].setJointTourComposition( chosenComposition ); + jointTourChoiceFreq[chosenFreqAlt][chosenComposition]++; + + + jointTourParticipation( jointTours[i] ); + + } + + } + + } + + + private void jointTourParticipation( TourIf jointTour ) { + + // get the Household object for this joint tour + HouseholdIf hh = dmuObject.getHouseholdObject(); + + // get the array of Person objects for this hh + PersonIf[] persons = hh.getPersons(); + + // define an ArrayList to hold indices of person objects participating in the joint tour + ArrayList jointTourPersonList = null; + + + // make sure each joint tour has a valid composition before going to the next one. + boolean validParty = false; + + + int adults = 0; + int children = 0; + + while ( !validParty ) { + + adults = 0; + children = 0; + + jointTourPersonList = new ArrayList(); + + + for (int p = 1; p < persons.length; p++) { + + jointTour.setPersonObject( persons[p] ); + + // if person type is inconsistent with tour composition, person's participation is by definition no, + // so skip making the choice and go to next person + switch ( jointTour.getJointTourComposition() ) { + + // adults only in joint tour + case 1: + if ( persons[p].getPersonIsAdult() == 1 ) { + jointTourParticipation.computeUtilities ( dmuObject, dmuObject.getDmuIndexValues(), participationAvailability, participationSample ); + Random hhRandom = hh.getHhRandom(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available adults only joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + adults++; + } + } + break; + + // children only in joint tour + case 2: + if ( persons[p].getPersonIsAdult() == 0 ) { + jointTourParticipation.computeUtilities ( dmuObject, dmuObject.getDmuIndexValues(), participationAvailability, participationSample ); + Random hhRandom = hh.getHhRandom(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available children only joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + children++; + } + } + break; + + // mixed, adults and children in joint tour + case 3: + IndexValues index = dmuObject.getDmuIndexValues(); + //if ( hh.getHhId() == 306640 ) + // index.setDebug(true); + jointTourParticipation.computeUtilities ( dmuObject, index, participationAvailability, participationSample ); + Random hhRandom = hh.getHhRandom(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available mixed adult/children joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + if ( persons[p].getPersonIsAdult() == 1 ) + adults++; + else + children++; + } + break; + + } + + } + + + // done with all persons, so see if the chosen participation is a valid composition, and if not, repeat the participation choice. + switch ( jointTour.getJointTourComposition() ) { + + case 1: + if ( adults > 1 && children == 0 ) + validParty = true; + break; + + case 2: + if ( adults == 0 && children > 1 ) + validParty = true; + break; + + case 3: + if ( adults > 0 && children > 0 ) + validParty = true; + break; + + } + + } // end while + + + // create an array of person indices for participation in the tour + byte[] personNums = new byte[jointTourPersonList.size()]; + for ( int i=0; i < personNums.length; i++ ) + personNums[i] = jointTourPersonList.get(i); + jointTour.setPersonNumArray( personNums ); + + + + // create a key to use for a frequency map for "JointTourPurpose_Composition_NumAdults_NumChildren" + String key = String.format( "%s_%d_%d_%d", jointTour.getTourPrimaryPurpose(), jointTour.getJointTourComposition(), adults, children ); + + int value = 0; + if ( partySizeFreq.containsKey( key ) ) + value = partySizeFreq.get( key ); + partySizeFreq.put( key, ++value ); + + } + + + + + /** + * creates the tour objects in the Household object given the chosen joint tour frequency alternative. + * @param chosenAlt + */ + private void createJointTours ( HouseholdIf household, int chosenAlt ) { + Object[] t1Data = null; + Object[] t2Data = null; + + switch ( chosenAlt ) { + + // no joint tours + case 1: + // call a method to create a joint tour array with zero elements. A zero element array indicates a 0_tours choice was made. + // as opposed to a null jointTours array which indicates that the household was not eligible to make any joint tours. + break; + + // 1 joint shop tour + case 2: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; break; + // 1 joint maint tour + case 3: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; break; + // 1 joint eat tour + case 4: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint visit tour + case 5: t1Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint disc tour + case 6: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint shop tour + case 7: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; break; + // 1 joint shop tour and 1 joint maint tour + case 8: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {maintPurposeIndex,maintPurposeString}; break; + // 1 joint shop tour and 1 joint eat tour + case 9: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint shop tour and 1 joint visit tour + case 10: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint shop tour and 1 joint discr tour + case 11: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint maint tour + case 12: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {maintPurposeIndex,maintPurposeString}; break; + // 1 joint maint tour and 1 joint eat tour + case 13: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint maint tour and 1 joint visit tour + case 14: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint maint tour and 1 joint discr tour + case 15: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint eat tour + case 16: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint eat tour and 1 joint visit tour + case 17: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint eat tour and 1 joint discr tour + case 18: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint visit tour + case 19: t1Data = new Object[] {socialPurposeIndex,socialPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint visit tour and 1 joint discr tour + case 20: t1Data = new Object[] {socialPurposeIndex,socialPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint discr tour + case 21: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + + } + + //create tours + if (t1Data == null) { + household.createJointTourArray(); + } else{ + if (t2Data == null) { + household.createJointTourArray(t1Data); + } else { + household.createJointTourArray(t1Data,t2Data); + } + } + + } + + + /** + * Logs the results of the model. + * + */ + public void logResults(){ + + String[] altLabels = jointTourFrequencyModel.getAlternativeNames(); + + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info("Joint Tour Frequency and Joint Tour Composition Model Results"); + + + logger.info(" "); + logger.info ( String.format( "%-5s %-20s %8s %8s %8s %8s", "alt", "alt name", "adult", "child", "mixed", "total" ) ); + + + // treat the first row of the table differently - no joint tours chosen and therefore no composition chosen. + // so we just want to print the total households chhosing no joint tours in the "total" column. + // later we'll add this total to the tanle total in the last row. + String logString = String.format( "%-5d %-20s", 1, altLabels[0] ); + for ( int j=0; j < 3; j++ ) + logString += String.format( " %8s", "N/A" ); + logString += String.format( " %8d", jointTourChoiceFreq[0][0] ); + logger.info ( logString ); + + + + + int[] columnTotals = new int[3]; + for ( int i=1; i < altLabels.length; i++ ) { + + logString = String.format( "%-5d %-20s", (i+1), altLabels[i] ); + + int rowTotal = 0; + for ( int j=0; j < columnTotals.length; j++ ) { + columnTotals[j] += jointTourChoiceFreq[i+1][j+1]; + rowTotal += jointTourChoiceFreq[i+1][j+1]; + logString += String.format( " %8d", jointTourChoiceFreq[i+1][j+1] ); + } + + logString += String.format( " %8d", rowTotal ); + logger.info ( logString ); + + } + + int rowTotal = 0; + logString = String.format( "%-5s %-20s", "total", "" ); + for ( int j=0; j < columnTotals.length; j++ ) { + rowTotal += columnTotals[j]; + logString += String.format( " %8d", columnTotals[j] ); + } + + rowTotal += jointTourChoiceFreq[0][0]; + logString += String.format( " %8d", rowTotal ); + logger.info ( logString ); + + + + logger.info(" "); + logger.info ( String.format( "Single person hhs could not produce joint tours: %d.", invalidCount[2] ) ); + logger.info ( String.format( "hhs with fewer than 2 persons leaving home could not produce joint tours: %d.", invalidCount[3] ) ); + logger.info ( String.format( "hhs with fewer than 1 non-preschool persons leaving home could not produce joint tours: %d.", invalidCount[4] ) ); + + logger.info(" "); + logger.info(" "); + logger.info(" "); + + + logger.info ( String.format( "%-5s %-10s %-10s %10s %10s %10s", "N", "Purpose", "Type", "Adults", "Children", "Freq" ) ); + + + int count = 1; + for ( String key : partySizeFreq.keySet() ) { + + int start = 0; + int end = 0; + int compIndex = 0; + int adults = 0; + int children = 0; + String indexString = ""; + String purpose = ""; + + start = 0; + end = key.indexOf( '_', start ); + purpose = key.substring( start, end ); + + start = end+1; + end = key.indexOf( '_', start ); + indexString = key.substring( start, end ); + compIndex = Integer.parseInt ( indexString ); + + start = end+1; + end = key.indexOf( '_', start ); + indexString = key.substring( start, end ); + adults = Integer.parseInt ( indexString ); + + start = end+1; + indexString = key.substring( start ); + children = Integer.parseInt ( indexString ); + + logger.info ( String.format( "%-5d %-10s %-10s %10d %10d %10d", count++, purpose, JOINT_TOUR_COMPOSITION_NAMES[compIndex], adults, children, partySizeFreq.get(key) ) ); + } + + + logger.info(" "); + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info(" "); + + } + + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/MatrixDataServer.java b/src/java/com/pb/models/ctrampIf/MatrixDataServer.java new file mode 100644 index 0000000..ae9de7f --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/MatrixDataServer.java @@ -0,0 +1,220 @@ +package com.pb.models.ctrampIf; + +import gnu.cajo.invoke.Remote; +import gnu.cajo.utils.ItemServer; +import org.apache.log4j.Logger; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; +import java.io.File; +import java.io.Serializable; + +import com.pb.common.calculator.DataEntry; +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.common.matrix.Matrix; +import com.pb.common.matrix.MatrixType; +import com.pb.common.matrix.MatrixReader; + + +/** + * @author Jim Hicks + * + * Class for managing matrix data in a remote process and accessed by UECs using RMI. + */ +public class MatrixDataServer implements MatrixDataServerIf, Serializable { + + protected static Logger logger = Logger.getLogger(MatrixDataServer.class); + + //version 2.3.2 drops the 32bit JVM stuff since not needed + private static final String VERSION = "2.3.2, 04jan2013"; + + // These are used if the server is started manually by running this class's main(). If so, these must be defined consistently with + // any class that acts as a client to the server, i.e. the client must know the address and port as well. + private static final String MATRIX_DATA_SERVER_ADDRESS = "127.0.0.1"; + private static final int MATRIX_DATA_SERVER_PORT = 1171; + public static final String MATRIX_DATA_SERVER_NAME = MatrixDataServer.class.getCanonicalName(); + private static final String MATRIX_DATA_SERVER_LABEL = "matrix server"; + + private static final boolean SAVE_MATRIX_DATA_IN_MAP = true; + + private HashMap matrixEntryMap; + private HashMap matrixMap; + + private boolean useMatrixMap; + + + public MatrixDataServer() { + + // create the HashMap objects to keep track of matrix data read by the server + matrixEntryMap = new HashMap(); + matrixMap = new HashMap(); + } + + + public String testRemote() { + logger.info("testRemote() called by remote process."); + return String.format("testRemote() method in %s called.", this.getClass().getCanonicalName() ); + } + + + public String testRemote( String remoteObjectName ) + { + logger.info("testRemote() called by remote process: " + remoteObjectName + "." ); + return String.format("testRemote() method in %s called by %s.", this.getClass().getCanonicalName(), remoteObjectName); + } + + + /** + * Return the Matrix object identified by the DataEntry argument. If it exists in the cache, + * return that object. If it does not yet exist, read the Matrix data, store in the cache, and return it. + * + * @param matrixEntry is an object with details about the name and location of a matrix read by a UEC object. + * @return a Matrix object from the cached set. + */ + public synchronized Matrix getMatrix( DataEntry matrixEntry ) { + + Matrix m; + + String name = matrixEntry.name; + + if ( matrixEntryMap.containsKey( name ) ) { + m = matrixMap.get( name ); + } + else { + m = readMatrix( matrixEntry ); + + if ( useMatrixMap ) { + matrixMap.put ( name, m ); + matrixEntryMap.put( name, matrixEntry ); + } + } + + return m; + } + + + public void clear() { + matrixMap.clear(); + matrixEntryMap.clear(); + } + + + public void setUseMatrixMap( boolean useMap ) { + useMatrixMap = useMap; + } + + + /* + * Read a matrix. + * + * @param matrixEntry a DataEntry describing the matrix to read + * @return a Matrix + */ + private Matrix readMatrix(DataEntry matrixEntry) { + + Matrix matrix; + String fileName = matrixEntry.fileName; + + if (matrixEntry.format.equalsIgnoreCase("emme2")) { + MatrixReader mr = MatrixReader.createReader(MatrixType.EMME2, new File(fileName)); + matrix = mr.readMatrix(matrixEntry.matrixName); + logger.info(String.format("read %s %s", fileName, matrixEntry.matrixName)); + + } else if (matrixEntry.format.equalsIgnoreCase("binary")) { + MatrixReader mr = MatrixReader.createReader(MatrixType.BINARY, new File(fileName)); + matrix = mr.readMatrix(); + logger.info(String.format("read %s %s", fileName, matrixEntry.matrixName)); + + } else if (matrixEntry.format.equalsIgnoreCase("zip") || matrixEntry.format.equalsIgnoreCase("zmx")) { + MatrixReader mr = MatrixReader.createReader(MatrixType.ZIP, new File(fileName)); + matrix = mr.readMatrix(); + logger.info(String.format("read %s %s", fileName, matrixEntry.matrixName)); + + } else if (matrixEntry.format.equalsIgnoreCase("tpplus")) { + MatrixReader mr = MatrixReader.createReader(MatrixType.TPPLUS, new File(fileName)); + matrix = mr.readMatrix(matrixEntry.matrixName); + logger.info(String.format("read %s %s", fileName, matrixEntry.matrixName)); + + } else if (matrixEntry.format.equalsIgnoreCase("transcad")) { + MatrixReader mr = MatrixReader.createReader(MatrixType.TRANSCAD, new File(fileName)); + matrix = mr.readMatrix(matrixEntry.matrixName); + logger.info(String.format("read %s %s", fileName, matrixEntry.matrixName)); + + } else { + throw new RuntimeException("unsupported matrix type: " + matrixEntry.format); + } + + + //Use token name from control file for matrix name (not name from underlying matrix) + matrix.setName(matrixEntry.name); + + return matrix; + } + + + + public void start32BitMatrixIoServer( MatrixType mType ) { + //do nothing + } + + + public void stop32BitMatrixIoServer() { + //do nothing + } + + + public static void main(String args[]) throws Exception { + + String serverAddress = MATRIX_DATA_SERVER_ADDRESS; + int serverPort = MATRIX_DATA_SERVER_PORT; + String className = MATRIX_DATA_SERVER_NAME; + String serverLabel = MATRIX_DATA_SERVER_LABEL; + boolean serverUseMap = SAVE_MATRIX_DATA_IN_MAP; + + for (int i=0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("-hostname")) + serverAddress = args[i+1]; + else if (args[i].equalsIgnoreCase("-port")) + serverPort = Integer.parseInt( args[i+1] ); + else if (args[i].equalsIgnoreCase("-label")) + serverLabel = args[i+1]; + else if (args[i].equalsIgnoreCase("-useMap")) + serverUseMap = Boolean.getBoolean( args[i+1] ); + } + + MatrixDataServer matrixServer = new MatrixDataServer(); + matrixServer.setUseMatrixMap( serverUseMap ); + + + // bind this concrete object with the cajo library objects for managing RMI + boolean serverWaiting = true; + int count = 0; + while ( serverWaiting ) { + try { + Remote.config( serverAddress, serverPort, null, 0 ); + ItemServer.bind( matrixServer, className ); + serverWaiting = false; + } + catch ( Exception e ) { + TimeUnit.SECONDS.sleep(1); + e.printStackTrace(); + System.out.println( "try number" + count++ ); + } + if ( count == 3 ) { + throw new RuntimeException(); + } + } + + + // log that the server started + System.out.println( String.format("%s version %s started on: %s:%d", serverLabel, VERSION, serverAddress, serverPort) ); + + + } + + public void writeMatrixFile(String fileName, Matrix[] m) { + + System.out.println( "write matrix not currently implemented" ); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/MatrixDataServerRmi.java b/src/java/com/pb/models/ctrampIf/MatrixDataServerRmi.java new file mode 100644 index 0000000..c7f4d0f --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/MatrixDataServerRmi.java @@ -0,0 +1,70 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; + +import com.pb.common.calculator.DataEntry; +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.common.matrix.Matrix; +import com.pb.common.matrix.MatrixType; +import com.pb.models.ctrampIf.UtilRmi; + +//import org.apache.log4j.Logger; + + +/** + * @author Jim Hicks + * + * Class for managing matrix data in a remote process and accessed by UECs using RMI. + */ +public class MatrixDataServerRmi implements MatrixDataServerIf, Serializable { + + //protected static Logger logger = Logger.getLogger(MatrixDataServerRmi.class); + + UtilRmi remote; + String connectString; + + + public MatrixDataServerRmi( String hostname, int port, String className ) { + + connectString = String.format("//%s:%d/%s", hostname, port, className ); + remote = new UtilRmi(connectString); + + } + + public void writeMatrixFile(String fileName, Matrix[] m){ + Object[] objArray = { fileName, m }; + remote.method("writeMatrixFile", objArray); + } + + public String testRemote() { + Object[] objArray = {}; + return (String)remote.method( "testRemote", objArray); + } + + public String testRemote( String remoteObjectName ) + { + Object[] objArray = { remoteObjectName }; + return (String) remote.method("testRemote", objArray); + } + + public void clear() { + Object[] objArray = {}; + remote.method( "clear", objArray); + } + + public Matrix getMatrix( DataEntry dataEntry ) { + Object[] objArray = { dataEntry }; + return (Matrix)remote.method( "getMatrix", objArray); + } + + public void start32BitMatrixIoServer( MatrixType mType ) { + Object[] objArray = { mType }; + remote.method( "start32BitMatrixIoServer", objArray); + } + + public void stop32BitMatrixIoServer() { + Object[] objArray = {}; + remote.method( "stop32BitMatrixIoServer", objArray); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/ModelStructure.java b/src/java/com/pb/models/ctrampIf/ModelStructure.java new file mode 100644 index 0000000..8d22199 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/ModelStructure.java @@ -0,0 +1,943 @@ +package com.pb.models.ctrampIf; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; +import java.util.TreeSet; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; + +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.TableDataSet; + +/** + * Holds the tour purpose list as well as the market segments for each tour. + * + * @author D. Ory + * + */ +public abstract class ModelStructure implements Serializable +{ + + + public static final String[] DC_SIZE_AREA_TYPE_BASED_SEGMENTS = {"CBD", "URBAN", "SUBURBAN", "RURAL" }; + + public static final String MANDATORY_CATEGORY = "MANDATORY"; + public static final String JOINT_NON_MANDATORY_CATEGORY = "JOINT_NON_MANDATORY"; + public static final String INDIVIDUAL_NON_MANDATORY_CATEGORY = "INDIVIDUAL_NON_MANDATORY"; + public static final String AT_WORK_CATEGORY = "AT_WORK"; + public static final String[] TOUR_CATEGORY_LABELS = { "", MANDATORY_CATEGORY, JOINT_NON_MANDATORY_CATEGORY, INDIVIDUAL_NON_MANDATORY_CATEGORY, AT_WORK_CATEGORY }; + + //public final String[] WORK_PURPOSE_SEGMENT_NAMES = { "low", "med", "high", "very high", "part time" }; + public final String[] WORK_PURPOSE_SEGMENT_NAMES = { "OCC1", "OCC2", "OCC3", "OCC4", "OCC5", "OCC6", "OCC7", "OCC8", "OCC9", "OCC10", "OCC11", "OCC12" }; + + public static final int MANDATORY_CATEGORY_INDEX = 1; + public static final int JOINT_NON_MANDATORY_CATEGORY_INDEX = 2; + public static final int INDIVIDUAL_NON_MANDATORY_CATEGORY_INDEX = 3; + public static final int AT_WORK_CATEGORY_INDEX = 4; + + public static final String MANDATORY_PATTERN = "M"; + public static final String NONMANDATORY_PATTERN = "N"; + public static final String HOME_PATTERN = "H"; + + public static final int FIRST_DEPART_HOUR = 4; + public static final int LAST_DEPART_HOUR = 24; + public static final int FIRST_TOD_INTERVAL_HOUR = 430; + public static final int LAST_TOD_INTERVAL_HOUR = 2400; + protected String[] TIME_PERIOD_LABELS; + + private HashMap indexTimePeriodMap; + private HashMap timePeriodIndexMap; + + protected int[] incomeSegmentDollarLimits; // upper limits of income ranges; 0-based; length of array gives the number of income segments; + + protected HashMap segmentedPurposeIndexMap; // segment names/indices map for purposes assigned to tours + protected HashMap segmentedIndexPurposeMap; // segment indices/names map for purposes assigned to tours + + private HashMap primaryTourPurposeNameIndexMap = new HashMap(); + private HashMap indexPrimaryTourPurposeNameMap = new HashMap(); + + public static final String WORK_PRIMARY_PURPOSE_NAME = "Work"; + public static final String UNIVERSITY_PRIMARY_PURPOSE_NAME = "University"; + public static final String SCHOOL_PRIMARY_PURPOSE_NAME = "School"; + public static final String ESCORT_PRIMARY_PURPOSE_NAME = "Escort"; + public static final String SHOPPING_PRIMARY_PURPOSE_NAME = "Shop"; + public static final String OTH_MAINT_PRIMARY_PURPOSE_NAME = "Maintenance"; + public static final String EAT_OUT_PRIMARY_PURPOSE_NAME = "EatingOut"; + public static final String VISITING_PRIMARY_PURPOSE_NAME = "Visiting"; + public static final String OTH_DISCR_PRIMARY_PURPOSE_NAME = "Discretionary"; + public static final String WORK_BASED_PRIMARY_PURPOSE_NAME = "Work-Based"; + + public static final int WORK_PRIMARY_PURPOSE_INDEX = 1; + public static final int UNIVERSITY_PRIMARY_PURPOSE_INDEX = 2; + public static final int SCHOOL_PRIMARY_PURPOSE_INDEX = 3; + public static final int ESCORT_PRIMARY_PURPOSE_INDEX = 4; + public static final int SHOPPING_PRIMARY_PURPOSE_INDEX = 5; + public static final int OTH_MAINT_PRIMARY_PURPOSE_INDEX = 6; + public static final int EAT_OUT_PRIMARY_PURPOSE_INDEX = 7; + public static final int VISITING_PRIMARY_PURPOSE_INDEX = 8; + public static final int OTH_DISCR_PRIMARY_PURPOSE_INDEX = 9; + public static final int WORK_BASED_PRIMARY_PURPOSE_INDEX = 10; + public static final int NUM_PRIMARY_PURPOSES = 10; + + public static final int WORKS_AT_HOME_ALTERNATUVE_INDEX = 2; + public static final int WORKS_AT_HOME_LOCATION_INDICATOR = 99999; + public static final int NOT_ENROLLED_SEGMENT_INDEX = 88888; + + public static final int WORK_PURPOSE_INDEX = 1; + public static final int UNIVERSITY_PURPOSE_INDEX = 2; + public static final int SCHOOL_PURPOSE_INDEX = 3; + public static final int ESCORT_PURPOSE_INDEX = 4; + public static final int SHOPPING_PURPOSE_INDEX = 5; + public static final int OTH_MAINT_PURPOSE_INDEX = 6; + public static final int EAT_OUT_PURPOSE_INDEX = 7; + public static final int SOCIAL_PURPOSE_INDEX = 8; + public static final int OTH_DISCR_PURPOSE_INDEX = 9; + public static final int AT_WORK_PURPOSE_INDEX = 10; + + public static final String WORK_PURPOSE_NAME = "work"; + public static final String UNIVERSITY_PURPOSE_NAME = "university"; + public static final String SCHOOL_PURPOSE_NAME = "school"; + public static final String ESCORT_PURPOSE_NAME = "escort"; + public static final String SHOPPING_PURPOSE_NAME = "shop"; + public static final String EAT_OUT_PURPOSE_NAME = "eatingout"; + public static final String OTH_MAINT_PURPOSE_NAME = "maintenance"; + public static final String SOCIAL_PURPOSE_NAME = "visiting"; + public static final String OTH_DISCR_PURPOSE_NAME = "discretionary"; + public static final String AT_WORK_PURPOSE_NAME = "work-based"; + public static final String AT_WORK_EAT_PURPOSE_NAME = "eat"; + public static final String AT_WORK_BUSINESS_PURPOSE_NAME = "business"; + public static final String AT_WORK_MAINT_PURPOSE_NAME = "maint"; + + public int AT_WORK_PURPOSE_INDEX_EAT; + public int AT_WORK_PURPOSE_INDEX_BUSINESS; + public int AT_WORK_PURPOSE_INDEX_MAINT; + + public String[] ESCORT_SEGMENT_NAMES; + public String[] AT_WORK_SEGMENT_NAMES; + + // TODO: Determine which of the following can be eliminated + protected HashMap dcSoaUecIndexMap; + protected HashMap dcUecIndexMap; + protected HashMap tourModeChoiceUecIndexMap; + + protected HashMap dcSizeDcModelPurposeMap; + protected HashMap dcModelDcSizePurposeMap; + + protected HashMap dcModelPurposeIndexMap; // segments + // for + // which + // dc + // soa alternative models + // are applied + protected HashMap dcModelIndexPurposeMap; // segments + // for + // which + // dc + // soa alternative models + // are applied + + protected HashMap dcSizeSegmentIndexMap; // segments + // for + // which + // separate dc size + // coefficients are + // specified + protected HashMap dcSizeIndexSegmentMap; + protected HashMap dcSizeArrayPurposeIndexMap; // segments + // for + // which + // dc + // size terms are stored + protected HashMap dcSizeArrayIndexPurposeMap; + protected HashMap> dcSizePurposeSegmentMap; + + private String dcSizeCoeffPurposeFieldName = "purpose"; + private String dcSizeCoeffSegmentFieldName = "segment"; + + // TODO meld with what jim is doing on this front + protected String[] mandatoryDcModelPurposeNames; + protected String[] jointDcModelPurposeNames; + protected String[] nonMandatoryDcModelPurposeNames; + protected String[] atWorkDcModelPurposeNames; + + protected String workPurposeName; + protected String universityPurposeName; + protected String schoolPurposeName; + + protected String[] workPurposeSegmentNames; + protected String[] universityPurposeSegmentNames; + protected String[] schoolPurposeSegmentNames; + + protected HashMap stopFreqUecIndexMap; + protected HashMap stopLocUecIndexMap; + protected HashMap tripModeChoiceUecIndexMap; + + protected String[] jtfAltLabels; + protected String[] awfAltLabels; + + + /** + * Assume name of the columns in the destination size coefficients file that + * contain the purpose strings is "purpose" and the column that contains the + * segment strings is "segment" + */ + public ModelStructure() + { + + dcModelPurposeIndexMap = new HashMap(); + dcModelIndexPurposeMap = new HashMap(); + dcSoaUecIndexMap = new HashMap(); + dcUecIndexMap = new HashMap(); + tourModeChoiceUecIndexMap = new HashMap(); + stopFreqUecIndexMap = new HashMap(); + stopLocUecIndexMap = new HashMap(); + tripModeChoiceUecIndexMap = new HashMap(); + + segmentedPurposeIndexMap = new HashMap(); + segmentedIndexPurposeMap = new HashMap(); + + + // create a mapping between primary purpose names and purpose indices + createPrimaryPurposeMappings(); + + createIndexTimePeriodMap(); + + } + + + // a derived class must implement these methods to retrieve purpose names for + // various personTypes making mandatory tours. + abstract public String getUniversityPurpose(); + + abstract public String getSchoolPurpose(int age); + + abstract public boolean getTourModeIsSov(int tourMode); + + abstract public boolean getTourModeIsSovOrHov(int tourMode); + + abstract public boolean getTourModeIsS2(int tourMode); + + abstract public boolean getTourModeIsS3(int tourMode); + + abstract public boolean getTourModeIsHov(int tourMode); + + abstract public boolean getTourModeIsNonMotorized(int tourMode); + + abstract public boolean getTourModeIsBike(int tourMode); + + abstract public boolean getTourModeIsWalk(int tourMode); + + abstract public boolean getTourModeIsWalkLocal(int tourMode); + + abstract public boolean getTourModeIsWalkPremium(int tourMode); + + abstract public boolean getTourModeIsTransit(int tourMode); + + abstract public boolean getTourModeIsDriveTransit(int tourMode); + + abstract public boolean getTourModeIsPnr(int tourMode); + + abstract public boolean getTourModeIsKnr(int tourMode); + + abstract public boolean getTourModeIsSchoolBus(int tourMode); + + abstract public boolean getTripModeIsSovOrHov(int tripMode); + + abstract public double[][] getCdap6PlusProps(); + + abstract public int getWorkLocationDefaultDepartPeriod(); + abstract public int getWorkLocationDefaultArrivePeriod(); + abstract public int getSchoolLocationDefaultDepartPeriod(); + abstract public int getSchoolLocationDefaultArrivePeriod(); + abstract public int getUniversityLocationDefaultDepartPeriod(); + abstract public int getUniversityLocationDefaultArrivePeriod(); + abstract public int getNonMandatoryLocationDefaultDepartPeriod(); + abstract public int getNonMandatoryLocationDefaultArrivePeriod(); + + abstract public String getPeriodLabel(int period); + + abstract public int getIntervalFor4Pm(); + abstract public int getIntervalFor7Pm(); + + abstract public int getPeriodIndex(int period); + + abstract public int[] getPeriodCombinationIndices(); + + abstract public int getPeriodCombinationIndex(int startPeriod, int endPeriod); + + abstract public void setIncomeSegments( int[] incomeBreakPoints ); + + abstract public int getIncomeSegment( int hhIncomeInDollars ); + + abstract public int getMaxTourModeIndex(); + + abstract public HashMap> getDcSizePurposeSegmentMap(); + + abstract public String[] getJtfAltLabels(); + abstract public void setJtfAltLabels( String[] labels ); + + private void createPrimaryPurposeMappings() + { + + primaryTourPurposeNameIndexMap.put(WORK_PRIMARY_PURPOSE_NAME.toLowerCase(), WORK_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(WORK_PRIMARY_PURPOSE_INDEX, WORK_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(UNIVERSITY_PRIMARY_PURPOSE_NAME.toLowerCase(), UNIVERSITY_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(UNIVERSITY_PRIMARY_PURPOSE_INDEX, UNIVERSITY_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(SCHOOL_PRIMARY_PURPOSE_NAME.toLowerCase(), SCHOOL_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(SCHOOL_PRIMARY_PURPOSE_INDEX, SCHOOL_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(ESCORT_PRIMARY_PURPOSE_NAME.toLowerCase(), ESCORT_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(ESCORT_PRIMARY_PURPOSE_INDEX, ESCORT_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(SHOPPING_PRIMARY_PURPOSE_NAME.toLowerCase(), SHOPPING_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(SHOPPING_PRIMARY_PURPOSE_INDEX, SHOPPING_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(OTH_MAINT_PRIMARY_PURPOSE_NAME.toLowerCase(), OTH_MAINT_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(OTH_MAINT_PRIMARY_PURPOSE_INDEX, OTH_MAINT_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(EAT_OUT_PRIMARY_PURPOSE_NAME.toLowerCase(), EAT_OUT_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(EAT_OUT_PRIMARY_PURPOSE_INDEX, EAT_OUT_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(VISITING_PRIMARY_PURPOSE_NAME.toLowerCase(), VISITING_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(VISITING_PRIMARY_PURPOSE_INDEX, VISITING_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(OTH_DISCR_PRIMARY_PURPOSE_NAME.toLowerCase(), OTH_DISCR_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(OTH_DISCR_PRIMARY_PURPOSE_INDEX, OTH_DISCR_PRIMARY_PURPOSE_NAME.toLowerCase()); + primaryTourPurposeNameIndexMap.put(WORK_BASED_PRIMARY_PURPOSE_NAME.toLowerCase(), WORK_BASED_PRIMARY_PURPOSE_INDEX); + indexPrimaryTourPurposeNameMap.put(WORK_BASED_PRIMARY_PURPOSE_INDEX, WORK_BASED_PRIMARY_PURPOSE_NAME.toLowerCase()); + + } + + // return the primary purpose string for the purposeName argument + public String getPrimaryPurposeString( String purposeName ) { + return getPurposeString( purposeName ); + } + + public int getPrimaryPurposeIndex (String primaryPurposeName ){ + return primaryTourPurposeNameIndexMap.get( primaryPurposeName ); + } + + // determine if the purpose string is a work purpose + private String getPurposeString( String purposeName ) { + String purpose = ""; + int index = purposeName.indexOf( '_' ); + + // if there's no '_', the purposeName has no segments. + if ( index < 0 ) { + purpose = purposeName; + } + // if there is a '_', the purpose is the substring preceding it. + else { + purpose = purposeName.substring(0, index); + } + return purpose; + } + + public String getPrimaryPurposeForIndex( int index ) { + return indexPrimaryTourPurposeNameMap.get( index ); + } + + + /** + * @return the HashMap object that maps primary tour purpose + * names common to all CTRAMP implementations to indices (1-10). + */ + public HashMap getPrimaryPurposeNameIndexMap() + { + return primaryTourPurposeNameIndexMap; + } + + /** + * @return the HashMap object that maps indices (1-10) to primary + * tour purpose names common to all CTRAMP implementations. + */ + public HashMap getIndexPrimaryPurposeNameMap() + { + return indexPrimaryTourPurposeNameMap; + } + + /** + * @param purposeKey is the "purpose" name used as a key for the map to get the + * associated UEC tab number. + * @return the tab number of the UEC control file for the purpose + */ + public int getSoaUecIndexForPurpose(String purposeKey) + { + return dcSoaUecIndexMap.get(purposeKey); + } + + /** + * @param purposeKey is the "purpose" name used as a key for the map to get the + * associated UEC tab number. + * @return the tab number of the UEC control file for the purpose + */ + public int getDcUecIndexForPurpose(String purposeKey) + { + return dcUecIndexMap.get(purposeKey); + } + + /** + * @param purposeKey is the "purpose" name used as a key for the map to get the + * associated UEC tab number. + * @return the tab number of the UEC control file for the purpose + */ + public int getTourModeChoiceUecIndexForPurpose(String purposeKey) + { + return tourModeChoiceUecIndexMap.get(purposeKey); + } + + public String[] getDcModelPurposeList(String tourCategory) + { + if (tourCategory.equalsIgnoreCase(MANDATORY_CATEGORY)) return mandatoryDcModelPurposeNames; + else if (tourCategory.equalsIgnoreCase(JOINT_NON_MANDATORY_CATEGORY)) return jointDcModelPurposeNames; + else if (tourCategory.equalsIgnoreCase(INDIVIDUAL_NON_MANDATORY_CATEGORY)) return nonMandatoryDcModelPurposeNames; + else if (tourCategory.equalsIgnoreCase(AT_WORK_CATEGORY)) return atWorkDcModelPurposeNames; + else return null; + } + + public String getDcSizeCoeffPurposeFieldName() + { + return dcSizeCoeffPurposeFieldName; + } + + public String getDcSizeCoeffSegmentFieldName() + { + return this.dcSizeCoeffSegmentFieldName; + } + + public String getAtWorkEatPurposeName() + { + return AT_WORK_EAT_PURPOSE_NAME; + } + + public String[] getAtWorkSegmentNames() + { + return AT_WORK_SEGMENT_NAMES; + } + + public String getAtWorkBusinessPurposeName() + { + return AT_WORK_BUSINESS_PURPOSE_NAME; + } + + public String getAtWorkMaintPurposeName() + { + return AT_WORK_MAINT_PURPOSE_NAME; + } + + public int getAtWorkEatPurposeIndex() + { + return AT_WORK_PURPOSE_INDEX_EAT; + } + + public int getAtWorkBusinessPurposeIndex() + { + return AT_WORK_PURPOSE_INDEX_BUSINESS; + } + + public int getAtWorkMaintPurposeIndex() + { + return AT_WORK_PURPOSE_INDEX_MAINT; + } + + + /* + * // The following are used to navigate the dcSize array public int + * getDcSizeArrayCategoryIndexOffset(String category){ if ( + * category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) return + * getDcSizeArrayMandatoryCategoryIndexOffset(); else if ( + * category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) return + * getDcSizeArrayJointCategoryIndexOffset(); else if ( category.equalsIgnoreCase( + * INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) return + * getDcSizeArrayIndivNonManCategoryIndexOffset(); else if ( + * category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) return + * getDcSizeArrayAtWorkCategoryIndexOffset(); else return -1; } public int + * getNumDcSizeArrayCategorySegments(String category){ if ( + * category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) return + * getNumDcSizeArrayMandatorySegments(); else if ( category.equalsIgnoreCase( + * JOINT_NON_MANDATORY_CATEGORY ) ) return getNumDcSizeArrayJointSegments(); else + * if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) return + * getNumDcSizeArrayIndivNonManSegments(); else if ( category.equalsIgnoreCase( + * AT_WORK_CATEGORY ) ) return getNumDcSizeArrayAtWorkSegments(); else return -1; + * } private int getDcSizeArrayMandatoryCategoryIndexOffset() { return 0; } + * private int getNumDcSizeArrayMandatorySegments() { return + * mandatoryDcModelPurposeNames.length; } private int + * getDcSizeArrayJointCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length + ESCORT_SEGMENT_NAMES.length; } private + * int getNumDcSizeArrayJointSegments() { return + * nonMandatoryDcModelPurposeNames.length - ESCORT_SEGMENT_NAMES.length; } + * private int getDcSizeArrayIndivNonManCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length; } private int + * getNumDcSizeArrayIndivNonManSegments() { return + * nonMandatoryDcModelPurposeNames.length; } private int + * getDcSizeArrayAtWorkCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length + nonMandatoryDcModelPurposeNames.length; + * } private int getNumDcSizeArrayAtWorkSegments() { return + * dcSizeArrayIndexPurposeMap.size() - getDcSizeArrayAtWorkCategoryIndexOffset(); + * } // The following are used to navigate the dcSize segments calculated public + * int getDcSizeSegmentCategoryIndexOffset(String category){ if ( + * category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) return + * getDcSizeSegmentMandatoryCategoryIndexOffset(); else if ( + * category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) return + * getDcSizeSegmentJointCategoryIndexOffset(); else if ( + * category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) return + * getDcSizeSegmentIndivNonManCategoryIndexOffset(); else if ( + * category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) return + * getDcSizeSegmentAtWorkCategoryIndexOffset(); else return -1; } public int + * getNumDcSizeSegmentCategorySegments(String category){ if ( + * category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) return + * getNumDcSizeSegmentMandatorySegments(); else if ( category.equalsIgnoreCase( + * JOINT_NON_MANDATORY_CATEGORY ) ) return getNumDcSizeSegmentJointSegments(); + * else if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) + * return getNumDcSizeSegmentIndivNonManSegments(); else if ( + * category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) return + * getNumDcSizeSegmentAtWorkSegments(); else return -1; } private int + * getDcSizeSegmentMandatoryCategoryIndexOffset() { return 0; } private int + * getNumDcSizeSegmentMandatorySegments() { return + * mandatoryDcModelPurposeNames.length; } private int + * getDcSizeSegmentJointCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length + ESCORT_SEGMENT_NAMES.length; } private + * int getNumDcSizeSegmentJointSegments() { return + * nonMandatoryDcModelPurposeNames.length - ESCORT_SEGMENT_NAMES.length; } + * private int getDcSizeSegmentIndivNonManCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length; } private int + * getNumDcSizeSegmentIndivNonManSegments() { return + * nonMandatoryDcModelPurposeNames.length; } private int + * getDcSizeSegmentAtWorkCategoryIndexOffset() { return + * mandatoryDcModelPurposeNames.length + nonMandatoryDcModelPurposeNames.length; + * } private int getNumDcSizeSegmentAtWorkSegments() { return + * dcSizeIndexSegmentMap.size() - getDcSizeSegmentAtWorkCategoryIndexOffset(); } + * public boolean isValidDcSizePurposeSegment ( String purposeName, String + * segmentName ){ boolean returnValue = false; String purpKey = + * purposeName.toLowerCase(); if ( dcSizePurposeSegmentMap.containsKey( purpKey ) + * ) { HashMap segmentNamesMap = dcSizePurposeSegmentMap.get( + * purpKey ); if ( segmentNamesMap.size() > 0 ) { String segKey = + * segmentName.toLowerCase(); if ( segmentNamesMap.containsKey( segKey ) ) + * returnValue = true; } } return returnValue; } public int + * getDcSizeArrayPurposeIndex( String purpose ) { return + * dcSizeArrayPurposeIndexMap.get(purpose); } public String + * getDcSizeArrayIndexPurpose( int index ) { return + * dcSizeArrayIndexPurposeMap.get(index); } public int getDcSizeSegmentIndex( + * String purpose ) { return dcSizeSegmentIndexMap.get(purpose); } public String + * getDcSizeIndexSegment( int index ) { return dcSizeIndexSegmentMap.get(index); + * } public String[] getDcSizeArrayPurposeStrings() { String[] names = new + * String[dcSizeArrayIndexPurposeMap.size()]; for ( Integer i : + * dcSizeArrayIndexPurposeMap.keySet() ) names[i] = + * dcSizeArrayIndexPurposeMap.get(i); return names; } public String[] + * getDcSizeSegmentStrings() { String[] names = new + * String[dcSizeIndexSegmentMap.size()]; for ( Integer i : + * dcSizeIndexSegmentMap.keySet() ) names[i] = dcSizeIndexSegmentMap.get(i); + * return names; } public int getDcModelPurposeIndex( String purposeName ) { + * return dcModelPurposeIndexMap.get( purposeName.toLowerCase() ); } public + * String getDcModelIndexPurpose( int purposeIndex ) { return + * dcModelIndexPurposeMap.get( purposeIndex ); } // determine if the purpose + * string is a work purpose public boolean getDcModelPurposeIsWorkPurpose( String + * purposeName ) { String purpose = getPurposeString( purposeName ); return + * purpose.equalsIgnoreCase( workPurposeName ); } // determine if the purpose + * string is a university purpose public boolean + * getDcModelPurposeIsUniversityPurpose( String purposeName ) { String purpose = + * getPurposeString( purposeName ); return purpose.equalsIgnoreCase( + * universityPurposeName ); } // determine if the purpose string is a school + * purpose public boolean getDcModelPurposeIsSchoolPurpose( String purposeName ) + * { String purpose = getPurposeString( purposeName ); return + * purpose.equalsIgnoreCase( schoolPurposeName ); } // determine if the purpose + * string is a work purpose private String getPurposeString( String purposeName ) + * { String purpose = ""; int index = purposeName.indexOf( '_' ); // if there's + * no '_', the purposeName has no segments. if ( index < 0 ) { purpose = + * purposeName; } // if there is a '_', the purpose is the substring preceding + * it. else { purpose = purposeName.substring(0, index); } return purpose; } + * public String getEscortPurposeName() { return ESCORT_PURPOSE_NAME; } public + * String[] getEscortSegmentNames() { return ESCORT_SEGMENT_NAMES; } public + * String getShoppingPurposeName() { return SHOPPING_PURPOSE_NAME; } public + * String getEatOutPurposeName() { return EAT_OUT_PURPOSE_NAME; } public String + * getOthMaintPurposeName() { return OTH_MAINT_PURPOSE_NAME; } public String + * getSocialPurposeName() { return SOCIAL_PURPOSE_NAME; } public String + * getOthDiscrPurposeName() { return OTH_DISCR_PURPOSE_NAME; } public int + * getStopFrequencyModelIndex( String tourPurposeName ){ return + * stopFreqUecIndexMap.get( tourPurposeName ); } public TreeSet + * getStopFreqModelSheetIndices() { TreeSet set = new + * TreeSet(); for ( int el : stopFreqUecIndexMap.values() ) set.add( el + * ); return set; } public int getStopLocationModelIndex( String stopPurposeName + * ){ return stopLocUecIndexMap.get( stopPurposeName ); } public + * Collection getStopLocModelSheetIndices() { return + * stopLocUecIndexMap.values(); } public int getTripModeChoiceModelIndex( String + * stopPurposeName ){ return tripModeChoiceUecIndexMap.get( stopPurposeName ); } + * public Collection getTripModeChoiceModelSheetIndices() { return + * tripModeChoiceUecIndexMap.values(); } public Set + * getTripModeChoiceModelPurposes() { return tripModeChoiceUecIndexMap.keySet(); + * } public int getDcSizeArrayIndexFromDcModelIndex( int dcModelIndex ){ String + * dcModelPurposeString = dcModelIndexPurposeMap.get( dcModelIndex ); String + * dcSizePurposeString = dcModelDcSizePurposeMap.get(dcModelPurposeString); int + * dcSizeArrayIndex = getDcSizeArrayPurposeIndex( dcSizePurposeString ); return + * dcSizeArrayIndex; } public String[] getJtfAltLabels() { return jtfAltLabels; } + * public String[] getAwfAltLabels() { return awfAltLabels; } + */ + + public String getEscortPurposeName() { + return ESCORT_PURPOSE_NAME; + } + + public String[] getEscortSegmentNames() { + return ESCORT_SEGMENT_NAMES; + } + + public String getShoppingPurposeName() { + return SHOPPING_PURPOSE_NAME; + } + + public String getEatOutPurposeName() { + return EAT_OUT_PURPOSE_NAME; + } + + public String getOthMaintPurposeName() { + return OTH_MAINT_PURPOSE_NAME; + } + + public String getSocialPurposeName() { + return SOCIAL_PURPOSE_NAME; + } + + public String getOthDiscrPurposeName() { + return OTH_DISCR_PURPOSE_NAME; + } + + + + private void createIndexTimePeriodMap(){ + indexTimePeriodMap = new HashMap(); + timePeriodIndexMap = new HashMap(); + + int numHours = LAST_DEPART_HOUR - FIRST_DEPART_HOUR; + int numHalfHours = numHours*2; + + TIME_PERIOD_LABELS = new String[numHalfHours+1]; + + for (int i=1; i <= numHalfHours; i++){ + int time = ((int)(i/2) + FIRST_DEPART_HOUR)*100 + (i%2)*30; + indexTimePeriodMap.put(i, time); + timePeriodIndexMap.put(time, i); + TIME_PERIOD_LABELS[i] = Integer.toString(time); + } + } + + public String[] getTimePeriodLabelArray(){ + return TIME_PERIOD_LABELS; + } + + public String getTimePeriodLabel(int timePeriodIndex){ + return TIME_PERIOD_LABELS[timePeriodIndex]; + } + + // time argument is specified as: 500 for 5 am, 530 for 5:30 am, 1530 for 3:30 pm, etc. + public int getTimePeriodIndexForTime(int time){ + return timePeriodIndexMap.get(time); + } + + public int getNumberOfTimePeriods(){ + return TIME_PERIOD_LABELS.length - 1; + } + + /** + * return the tod skim period + */ + public int getTod(int period) { + + int modelPeriod = 0; + + if ( period >= 1 && period < 4 ) + modelPeriod = 1; + else if ( period < 6 ) + modelPeriod = 2; + else if ( period < 10 ) + modelPeriod = 3; + else if ( period < 12 ) + modelPeriod = 4; + else if ( period < 20 ) + modelPeriod = 5; + else if ( period < 24 ) + modelPeriod = 6; + else if ( period < 28 ) + modelPeriod = 7; + else if ( period < 32 ) + modelPeriod = 8; + else + modelPeriod = 1; + + return(modelPeriod); + } + + public String[] getAwfAltLabels() + { + return awfAltLabels; + } + + + // determine if the purpose string is a work purpose + public boolean getDcModelPurposeIsWorkPurpose( String purposeName ) { + String purpose = getPurposeString( purposeName ); + return purpose.equalsIgnoreCase( workPurposeName ); + } + + // determine if the purpose string is a university purpose + public boolean getDcModelPurposeIsUniversityPurpose( String purposeName ) { + String purpose = getPurposeString( purposeName ); + return purpose.equalsIgnoreCase( universityPurposeName ); + } + + // determine if the purpose string is a school purpose + public boolean getDcModelPurposeIsSchoolPurpose( String purposeName ) { + String purpose = getPurposeString( purposeName ); + return purpose.equalsIgnoreCase( schoolPurposeName ); + } + + + public int getDcModelPurposeIndex( String purposeName ) { + return dcModelPurposeIndexMap.get( purposeName.toLowerCase() ); + } + + public int getStopFrequencyModelIndex( String tourPurposeName ){ + return stopFreqUecIndexMap.get( tourPurposeName ); + } + + public TreeSet getStopFreqModelSheetIndices() { + TreeSet set = new TreeSet(); + for ( int el : stopFreqUecIndexMap.values() ) + set.add( el ); + return set; + } + + public int getStopLocationModelIndex( String stopPurposeName ){ + return stopLocUecIndexMap.get( stopPurposeName ); + } + + public Collection getStopLocModelSheetIndices() { + return stopLocUecIndexMap.values(); + } + + public int getTripModeChoiceModelIndex( String tourPurposeName ){ + return tripModeChoiceUecIndexMap.get( tourPurposeName ); + } + + public Collection getTripModeChoiceModelSheetIndices() { + return tripModeChoiceUecIndexMap.values(); + } + + public Set getTripModeChoiceModelPurposes() { + return tripModeChoiceUecIndexMap.keySet(); + } + + public boolean isValidDcSizePurposeSegment ( String purposeName, String segmentName ){ + boolean returnValue = false; + String purpKey = purposeName.toLowerCase(); + if ( dcSizePurposeSegmentMap.containsKey( purpKey ) ) { + HashMap segmentNamesMap = dcSizePurposeSegmentMap.get( purpKey ); + if ( segmentNamesMap.size() > 0 ) { + String segKey = segmentName.toLowerCase(); + if ( segmentNamesMap.containsKey( segKey ) ) + returnValue = true; + } + } + return returnValue; + } + + public String[] getDcSizeArrayPurposeStrings() { + String[] names = new String[dcSizeArrayIndexPurposeMap.size()]; + for ( Integer i : dcSizeArrayIndexPurposeMap.keySet() ) + names[i] = dcSizeArrayIndexPurposeMap.get(i); + return names; + } + + // The following are used to navigate the dcSize array + + public int getDcSizeArrayCategoryIndexOffset(String category){ + if ( category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) + return getDcSizeArrayMandatoryCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) + return getDcSizeArrayJointCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) + return getDcSizeArrayIndivNonManCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) + return getDcSizeArrayAtWorkCategoryIndexOffset(); + else + return -1; + } + + public int getNumDcSizeArrayCategorySegments(String category){ + if ( category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) + return getNumDcSizeArrayMandatorySegments(); + else if ( category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) + return getNumDcSizeArrayJointSegments(); + else if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) + return getNumDcSizeArrayIndivNonManSegments(); + else if ( category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) + return getNumDcSizeArrayAtWorkSegments(); + else + return -1; + } + + private int getDcSizeArrayMandatoryCategoryIndexOffset() { + return 0; + } + + private int getNumDcSizeArrayMandatorySegments() { + return mandatoryDcModelPurposeNames.length; + } + + private int getDcSizeArrayJointCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length + ESCORT_SEGMENT_NAMES.length; + } + + private int getNumDcSizeArrayJointSegments() { + return nonMandatoryDcModelPurposeNames.length - ESCORT_SEGMENT_NAMES.length; + } + + private int getDcSizeArrayIndivNonManCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length; + } + + private int getNumDcSizeArrayIndivNonManSegments() { + return nonMandatoryDcModelPurposeNames.length; + } + + private int getDcSizeArrayAtWorkCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length + nonMandatoryDcModelPurposeNames.length; + } + + private int getNumDcSizeArrayAtWorkSegments() { + return dcSizeArrayIndexPurposeMap.size() - getDcSizeArrayAtWorkCategoryIndexOffset(); + } + + + + + // The following are used to navigate the dcSize segments calculated + + public int getDcSizeSegmentCategoryIndexOffset(String category){ + if ( category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) + return getDcSizeSegmentMandatoryCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) + return getDcSizeSegmentJointCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) + return getDcSizeSegmentIndivNonManCategoryIndexOffset(); + else if ( category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) + return getDcSizeSegmentAtWorkCategoryIndexOffset(); + else + return -1; + } + + public int getNumDcSizeSegmentCategorySegments(String category){ + if ( category.equalsIgnoreCase( MANDATORY_CATEGORY ) ) + return getNumDcSizeSegmentMandatorySegments(); + else if ( category.equalsIgnoreCase( JOINT_NON_MANDATORY_CATEGORY ) ) + return getNumDcSizeSegmentJointSegments(); + else if ( category.equalsIgnoreCase( INDIVIDUAL_NON_MANDATORY_CATEGORY ) ) + return getNumDcSizeSegmentIndivNonManSegments(); + else if ( category.equalsIgnoreCase( AT_WORK_CATEGORY ) ) + return getNumDcSizeSegmentAtWorkSegments(); + else + return -1; + } + + private int getDcSizeSegmentMandatoryCategoryIndexOffset() { + return 0; + } + + private int getNumDcSizeSegmentMandatorySegments() { + return mandatoryDcModelPurposeNames.length; + } + + private int getDcSizeSegmentJointCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length + ESCORT_SEGMENT_NAMES.length; + } + + private int getNumDcSizeSegmentJointSegments() { + return nonMandatoryDcModelPurposeNames.length - ESCORT_SEGMENT_NAMES.length; + } + + private int getDcSizeSegmentIndivNonManCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length; + } + + private int getNumDcSizeSegmentIndivNonManSegments() { + return nonMandatoryDcModelPurposeNames.length; + } + + private int getDcSizeSegmentAtWorkCategoryIndexOffset() { + return mandatoryDcModelPurposeNames.length + nonMandatoryDcModelPurposeNames.length; + } + + private int getNumDcSizeSegmentAtWorkSegments() { + return dcSizeIndexSegmentMap.size() - getDcSizeSegmentAtWorkCategoryIndexOffset(); + } + + public int getNumEscortSegments() { + return ESCORT_SEGMENT_NAMES.length; + } + + + public String[] getDcSizeSegmentStrings() { + String[] names = new String[dcSizeIndexSegmentMap.size()]; + for ( Integer i : dcSizeIndexSegmentMap.keySet() ) + names[i] = dcSizeIndexSegmentMap.get(i); + return names; + } + + public int getDcSizeArrayIndexFromDcModelIndex( int dcModelIndex ){ + String dcModelPurposeString = dcModelIndexPurposeMap.get( dcModelIndex ); + String dcSizePurposeString = dcModelDcSizePurposeMap.get(dcModelPurposeString); + int dcSizeArrayIndex = getDcSizeArrayPurposeIndex( dcSizePurposeString ); + return dcSizeArrayIndex; + } + + public int getDcSizeArrayPurposeIndex( String purpose ) { + return dcSizeArrayPurposeIndexMap.get(purpose); + } + + public String getDcSizeArrayIndexPurpose( int index ) { + return dcSizeArrayIndexPurposeMap.get(index); + } + + public String getWorkPurposeFromIncomeInDollars( int hhIncomeInDollars ) { + return getWorkPurposeFromIncomeInDollars( false, hhIncomeInDollars ); + } + + public String getWorkPurposeFromIncomeInDollars( boolean isPtWorker, int hhIncomeInDollars ) { + if ( isPtWorker ) { + return (workPurposeName + "_" + WORK_PURPOSE_SEGMENT_NAMES[WORK_PURPOSE_SEGMENT_NAMES.length-1]).toLowerCase(); + } else { + int incomeSegment = getIncomeSegment(hhIncomeInDollars); + return (workPurposeName + "_" + WORK_PURPOSE_SEGMENT_NAMES[incomeSegment-1]).toLowerCase(); + } + } + + public String getWorkPurposeFromOccupation( int occupation ) { + return (workPurposeName + "_" + WORK_PURPOSE_SEGMENT_NAMES[occupation-1]).toLowerCase(); + } + + public void setSegmentedPurposeIndex( String purpose, int index ) { + segmentedPurposeIndexMap.put( purpose, index ); + } + + public void setSegmentedIndexPurpose( int index, String purpose ) { + segmentedIndexPurposeMap.put( index, purpose ); + } + + public int getSegmentedIndexForPurpose( String purpose ) { + return segmentedPurposeIndexMap.get( purpose ); + } + + public String getSegmentedPurposeForIndex( int index ) { + return segmentedIndexPurposeMap.get( index ); + } + + public HashMap getSegmentedPurposeIndexMap() { + return segmentedPurposeIndexMap; + } + + public HashMap getSegmentedIndexPurposeMap() { + return segmentedIndexPurposeMap; + } + + public int getNumIncomeSegments() { + return incomeSegmentDollarLimits.length; + } + + + +} diff --git a/src/java/com/pb/models/ctrampIf/MyLogit.java b/src/java/com/pb/models/ctrampIf/MyLogit.java new file mode 100644 index 0000000..63225d1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/MyLogit.java @@ -0,0 +1,95 @@ +package com.pb.models.ctrampIf; + +import com.pb.common.math.MathUtil; +import com.pb.common.model.Alternative; +import com.pb.common.model.LogitModel; +import com.pb.common.model.ModelException; + +public class MyLogit + extends LogitModel +{ + + private static final int MAX_EXP_ARGUMENT = 400; + + private double[] utilities; + private double[] util; + private double[] constant; + private String[] altName; + + public MyLogit(String n, int numberOfAlternatives) + { + super(n, numberOfAlternatives); + + utilities = new double[numberOfAlternatives]; + util = new double[numberOfAlternatives]; + constant = new double[numberOfAlternatives]; + altName = new String[numberOfAlternatives]; + } + + /** + * Overrides the base class getUtility() method to call a method to return the + * array of exponentiated utilities, having passed to it an array of utilities. + * + * @return The composite utility (logsum value) of all the alternatives. + */ + public double getUtility() throws ModelException + { + + double sum = 0; + double base = 0; + + // get the array of utility values to be exponentiated from the alternatives + // objects. + int i = 0; + for (int alt = 0; alt < alternatives.size(); ++alt) + { + Alternative thisAlt = (Alternative) alternatives.get(alt); + if (thisAlt.isAvailable()) + { + + // assign attributes of the alternatives + util[i] = thisAlt.getUtility(); + constant[i] = thisAlt.getConstant(); + altName[i] = thisAlt.getName(); + + // if alternative has a very large negative utility, it isn't + // available + if (util[i] + constant[i] < -MAX_EXP_ARGUMENT) + { + utilities[i] = -MAX_EXP_ARGUMENT; + } else + { + utilities[i] = dispersionParameter * (util[i] + constant[i]); + setAvailability(true); + } + + i++; + } else + { + utilities[i++] = -MAX_EXP_ARGUMENT; + } + } + + // exponentiate the utilities array and save result in expUtilities. + MathUtil.expArray( utilities, expUtilities ); + + // sum the exponentiated utilities + for (i = 0; i < expUtilities.length; i++) + sum += expUtilities[i]; + + if (isAvailable()) + { + base = (1 / dispersionParameter) * MathUtil.log(sum); + + if (Double.isNaN(base)) { + throw new ModelException(ModelException.INVALID_UTILITY); + } + + return base; + } + + // if nothing avaiable, return a bad utilty + return -999; + } + +} diff --git a/src/java/com/pb/models/ctrampIf/ParkingChoiceDMU.java b/src/java/com/pb/models/ctrampIf/ParkingChoiceDMU.java new file mode 100644 index 0000000..b7f45b1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/ParkingChoiceDMU.java @@ -0,0 +1,135 @@ +package com.pb.models.ctrampIf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.HashMap; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +/** + * @author crf
+ * Started: Apr 14, 2009 1:34:03 PM + */ +public class ParkingChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(ParkingChoiceDMU.class); + + protected HashMap methodIndexMap; + + protected HashMap averageDailyHoursParkedMap; // key: purpose name, value: average hours parked per day by purpose + + protected IndexValues dmuIndex; + protected TazDataIf tazDataManager; + + protected TourIf tour; + protected int[] parkTazs; + + + public ParkingChoiceDMU(TazDataIf tazDataManager) { + this.tazDataManager = tazDataManager; + dmuIndex = new IndexValues(); + } + + + + + + public void setDmuState(HouseholdIf hh, int originZone, int destZone) { + setDmuIndexValues( hh.getHhId(), originZone, destZone, hh.getDebugChoiceModels() ); + } + + private void setDmuIndexValues(int hhId, int origTaz, int destTaz, boolean hhDebug) { + dmuIndex.setHHIndex(hhId); + dmuIndex.setOriginZone(origTaz); + dmuIndex.setDestZone(destTaz); + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel (""); + + if ( hhDebug ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ("Debug Parking Choice UEC"); + } + + } + + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + /** + * + * @return 1 if dest is in CBD + */ + public int getParkTazCbdAreaTypeAlt( int alt ){ + // parkTazs array is zero-based. + int taz = parkTazs[alt-1]; + return tazDataManager.getZoneIsCbd( taz ); + } + + /** + * get the hourly parking rate for the parking location alternative, and multiply + * by the average daily hours parking for the tour purpose. + * + * @return daily parking cost for the parking location alternative + */ + public float getParkingCostAlt( int alt ){ + int taz = parkTazs[alt-1]; + float rate = tazDataManager.getZoneTableValue( taz, tazDataManager.getZonalParkRateFieldName() ); + float hours = averageDailyHoursParkedMap.get( tour.getTourPrimaryPurpose() ); + + return hours * rate; + } + + public float getParkTotAlt( int alt ){ + int taz = parkTazs[alt-1]; + return tazDataManager.getZonalParkTot()[taz-1]; + } + + public void setParkTazArray ( int[] parkTazs ){ + this.parkTazs = parkTazs; + } + + protected int getTourIsJoint() { + return tour.getTourCategoryIsJointNonMandatory() ? 1 : 0; + } + + public float getParkTot(){ + int dest = dmuIndex.getDestZone(); + return tazDataManager.getZonalParkTot()[dest-1]; + } + + public void setTourObject( TourIf tour ) { + this.tour = tour; + } + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/PersonIf.java b/src/java/com/pb/models/ctrampIf/PersonIf.java new file mode 100644 index 0000000..fffae01 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/PersonIf.java @@ -0,0 +1,370 @@ +package com.pb.models.ctrampIf; + +import java.util.ArrayList; +import org.apache.log4j.Logger; + +public interface PersonIf +{ + + public static final int MIN_ADULT_AGE = 19; + public static final int MIN_STUDENT_AGE = 5; + // person type strings used for data summaries + public static final String PERSON_TYPE_FULL_TIME_WORKER_NAME = "Full-time worker"; + public static final String PERSON_TYPE_PART_TIME_WORKER_NAME = "Part-time worker"; + public static final String PERSON_TYPE_UNIVERSITY_STUDENT_NAME = "University student"; + public static final String PERSON_TYPE_NON_WORKER_NAME = "Non-worker"; + public static final String PERSON_TYPE_RETIRED_NAME = "Retired"; + public static final String PERSON_TYPE_STUDENT_DRIVING_NAME = "Student of driving age"; + public static final String PERSON_TYPE_STUDENT_NON_DRIVING_NAME = "Student of non-driving age"; + public static final String PERSON_TYPE_PRE_SCHOOL_CHILD_NAME = "Child too young for school"; + public static final String[] personTypeNameArray = { + PERSON_TYPE_FULL_TIME_WORKER_NAME, PERSON_TYPE_PART_TIME_WORKER_NAME, + PERSON_TYPE_UNIVERSITY_STUDENT_NAME, PERSON_TYPE_NON_WORKER_NAME, + PERSON_TYPE_RETIRED_NAME, PERSON_TYPE_STUDENT_DRIVING_NAME, + PERSON_TYPE_STUDENT_NON_DRIVING_NAME, PERSON_TYPE_PRE_SCHOOL_CHILD_NAME}; + public static final String EMPLOYMENT_CATEGORY_FULL_TIME_WORKER_NAME = "Full-time worker"; + public static final String EMPLOYMENT_CATEGORY_PART_TIME_WORKER_NAME = "Part-time worker"; + public static final String EMPLOYMENT_CATEGORY_NOT_EMPLOYED_NAME = "Not employed"; + public static final String EMPLOYMENT_CATEGORY_UNDER_AGE_16_NAME = "Under age 16"; + public static final String[] employmentCategoryNameArray = { + EMPLOYMENT_CATEGORY_FULL_TIME_WORKER_NAME, EMPLOYMENT_CATEGORY_PART_TIME_WORKER_NAME, + EMPLOYMENT_CATEGORY_NOT_EMPLOYED_NAME, EMPLOYMENT_CATEGORY_UNDER_AGE_16_NAME}; + public static final String STUDENT_CATEGORY_GRADE_OR_HIGH_SCHOOL_NAME = "Grade or high school"; + public static final String STUDENT_CATEGORY_COLLEGE_OR_HIGHER_NAME = "College or higher"; + public static final String STUDENT_CATEGORY_NOT_STUDENT_NAME = "Not student"; + public static final String[] studentCategoryNameArray = { + STUDENT_CATEGORY_GRADE_OR_HIGH_SCHOOL_NAME, STUDENT_CATEGORY_COLLEGE_OR_HIGHER_NAME, + STUDENT_CATEGORY_NOT_STUDENT_NAME }; + + public abstract TourIf makeDefaultTour( int purposeIndex ); + + public abstract HouseholdIf getHouseholdObject(); + + public abstract ArrayList getListOfWorkTours(); + + public abstract ArrayList getListOfSchoolTours(); + + public abstract ArrayList getListOfIndividualNonMandatoryTours(); + + public abstract ArrayList getListOfAtWorkSubtours(); + + public abstract byte[] getTimeWindows(); + + public abstract void initializeWindows(); + + public abstract void resetTimeWindow(int startHour, int endHour); + public void resetTimeWindow(); + + + // code the timw window array for this tour being scheduled. + // 0: unscheduled, 1: scheduled, middle of tour, 2: scheduled, start of tour,, 3: scheduled, end of tour, + // 4: scheduled, end of previous tour, start of current tour or end of current tour, start of subsequent tour; + // or current tour start/end same hour. + public abstract void scheduleWindow(int start, int end); + + public abstract boolean[] getAvailableTimeWindows(int[] altStarts, int[] altEnds); + + public abstract boolean isWindowAvailable(int start, int end); + + /** + * @return true if the window for the argument is the end of a previously scheduled tour + * and this hour does not overlap with any other tour. + */ + public abstract boolean isPreviousArrival(int hour); + + /** + * @return true if the window for the argument is the start of a previously scheduled tour + * and this hour does not overlap with any other tour. + */ + public abstract boolean isPreviousDeparture(int hour); + + public abstract boolean isPeriodAvailable(int period); + + public abstract void setPersId(int id); + + public abstract void setWorkLocationPurposeIndex(int workPurpose); + + public abstract void setUniversityLocationPurposeIndex(int universityPurpose); + + public abstract void setSchoolLocationPurposeIndex(int schoolPurpose); + + public abstract void setPersAge(int age); + + public abstract void setPersGender(int gender); + + public abstract void setPersEmploymentCategory(int category); + + public abstract void setPersStudentCategory(int category); + + public abstract void setPersonTypeCategory(int personTypeCategory); + + public abstract void setValueOfTime(float vot); + + public abstract void setWorkLoc(int loc); + + public abstract void setWorkLocSubzone(int subzone); + + public abstract void setSchoolLoc(int loc); + + public abstract void setSchoolLocSubzone(int subzone); + + public abstract void setFreeParkingAvailableResult(int fpResult); + + public abstract int getFreeParkingAvailableResult(); + + public abstract void setImtfChoice(int choice); + + public abstract void setInmtfChoice(int choice); + + public abstract int getImtfChoice(); + + public abstract int getInmtfChoice(); + + public abstract void clearIndividualNonMandatoryToursArray(); + + public abstract void createIndividualNonMandatoryTours(int numberOfTours, String purposeName, ModelStructure modelStructure); + + public abstract void createWorkTours(int numberOfTours, int startId, String tourPurpose, ModelStructure modelStructure); + + public abstract void clearAtWorkSubtours(); + + public abstract void createAtWorkSubtour(int id, int choice, int workTaz, int workSubZone, String tourPurpose, ModelStructure modelStructure); + + public abstract void createSchoolTours(int numberOfTours, int startId, String tourPurpose, ModelStructure modelStructure); + + public abstract int getWorkLocationPurposeIndex(); + + public abstract int getUniversityLocationPurposeIndex(); + + public abstract int getSchoolLocationPurposeIndex(); + + public abstract void setDailyActivityResult(String activity); + + public abstract int getPersonIsChildUnder16WithHomeOrNonMandatoryActivity(); + + public abstract int getAge(); + + public abstract int getHomemaker(); + + public abstract int getGender(); + + public abstract int getPersonIsFemale(); + + public abstract int getPersonIsMale(); + + public abstract int getPersonId(); + + public abstract int getPersonNum(); + + public abstract String getPersonType(); + + public abstract int getPersonTypeNumber(); + + public abstract String getPersonEmploymentCategory(); + + public abstract String getPersonStudentCategory(); + + public abstract float getValueOfTime(); + + public abstract int getPersonWorkLocationZone(); + + public abstract int getPersonWorkLocationSubZone(); + + public abstract int getPersonSchoolLocationSubZone(); + + public abstract int getPersonSchoolLocationZone(); + + public abstract String getCdapActivity(); + + public abstract int getUsualWorkLocation(); + + public abstract int getUsualSchoolLocation(); + + public abstract int getNumWorkTours(); + + public abstract int getNumUniversityTours(); + + public abstract int getNumSchoolTours(); + + public abstract int getNumIndividualEscortTours(); + + public abstract int getNumIndividualShoppingTours(); + + public abstract int getNumTotalIndivTours(); + + public abstract int getNumIndividualEatOutTours(); + + public abstract int getNumIndividualOthMaintTours(); + + public abstract int getNumIndividualSocialTours(); + + public abstract int getNumIndividualOthDiscrTours(); + + public abstract int getNumMandatoryTours(); + + public abstract int getNumJointShoppingTours(); + + public abstract int getNumJointOthMaintTours(); + + public abstract int getNumJointEatOutTours(); + + public abstract int getNumJointSocialTours(); + + public abstract int getNumJointOthDiscrTours(); + + public abstract void computeIdapResidualWindows(); + + public abstract int getWindowBeforeFirstMandJointTour(); + + public abstract int getWindowBetweenFirstLastMandJointTour(); + + public abstract int getWindowAfterLastMandJointTour(); + + /** + * determine if person is a worker (indepdent of person type). + * @return 1 if worker, 0 otherwise. + */ + public abstract int getPersonIsWorker(); + + /** + * Determine if person is a student (of any age, independent of person type) + * @return 1 if student, 0 otherwise + */ + public abstract int getPersonIsStudent(); + + public abstract int getPersonIsUniversityStudent(); + + public abstract int getPersonIsStudentDriving(); + + public abstract int getPersonIsStudentNonDriving(); + + /** + * Determine if person is a full-time worker (independent of person type) + * @return 1 if full-time worker, 0 otherwise + */ + public abstract int getPersonIsFullTimeWorker(); + + /** + * Determine if person is a part-time worker (indepdent of person type) + */ + public abstract int getPersonIsPartTimeWorker(); + + public abstract int getPersonTypeIsFullTimeWorker(); + + public abstract int getPersonTypeIsPartTimeWorker(); + + public abstract int getPersonIsNonWorkingAdultUnder65(); + + public abstract int getPersonIsNonWorkingAdultOver65(); + + public abstract int getPersonIsPreschoolChild(); + + public abstract int getPersonIsAdult(); + + /** + * return maximum hours of overlap between this person and other adult persons in the household. + * @return the most number of hours mutually available between this person and other adult household members + */ + public abstract int getMaxAdultOverlaps(); + + /** + * set maximum hours of overlap between this person and other adult persons in the household. + * @param overlaps are the most number of hours mutually available between this person and other adult household members + */ + public abstract void setMaxAdultOverlaps(int overlaps); + + /** + * return maximum hours of overlap between this person and other children in the household. + * @return the most number of hours mutually available between this person and other child household members + */ + public abstract int getMaxChildOverlaps(); + + /** + * set maximum hours of overlap between this person and other children in the household. + * @param overlaps are the most number of hours mutually available between this person and other child household members + */ + public abstract void setMaxChildOverlaps(int overlaps); + + /** + * return available time window for this person in the household. + * @return the total number of hours available for this person + */ + public abstract int getAvailableWindow(); + + public abstract void setTimeWindows(byte[] win); + + public abstract void initializeForAoRestart(); + + public abstract void initializeForImtfRestart(); + + /** + * initialize the person attributes and tour objects for restarting the model at joint tour frequency + */ + public abstract void initializeForJtfRestart(); + + /** + * initialize the person attributes and tour objects for restarting the model at individual non-mandatory tour frequency. + */ + public abstract void initializeForInmtfRestart(); + + /** + * initialize the person attributes and tour objects for restarting the model at at-work sub-tour frequency. + */ + public abstract void initializeForAwfRestart(); + + /** + * initialize the person attributes and tour objects for restarting the model at stop frequency. + */ + public abstract void initializeForStfRestart(); + + public abstract void logPersonObject(Logger logger, int totalChars); + + public abstract void logTourObject(Logger logger, int totalChars, TourIf tour); + + public abstract void logEntirePersonObject(Logger logger); + + public void setPersonIsHighSchool(boolean flag); + + public int getPersonIsHighSchool(); + + public void setPersonIsGradeSchool(boolean flag); + + public int getPersonIsGradeSchool(); + + public int getPersonIsHighSchoolGraduate(); + + public int getMaximumContinuousAvailableWindow(); + + public int getMaximumContinuousPairwiseAvailableWindow( byte[] otherWindow ); + + public int getPersonIsChild6To18WithoutMandatoryActivity(); + + public int getPersonEducAttainment(); + + public void setPersonEducAttainment(int educAttainCode); + + public int getPersonIndustryCensus(); + + public void setPersonIndustryCensus(int indCensusCode); + + public int getPersonWorkerOccupation(); + + public void setPersonWorkerOccupation(int workerOccupation); + + public abstract float getWalkTimeWeight(); + + public abstract void setWalkTimeWeight(float walkTimeWeight); + + public abstract float getWalkSpeed(); + + public abstract void setWalkSpeed(float walkSpeed); + + public abstract float getMaxWalk(); + + public abstract void setMaxWalk(float maxWalk); + + public abstract int getUserClass(String type); + + public abstract void setUserClass(String type, int userClass); + +} diff --git a/src/java/com/pb/models/ctrampIf/SoaDMU.java b/src/java/com/pb/models/ctrampIf/SoaDMU.java new file mode 100644 index 0000000..92e5e4c --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/SoaDMU.java @@ -0,0 +1,9 @@ +package com.pb.models.ctrampIf; + +/** + * @author crf
+ * Started: Nov 15, 2008 3:25:49 PM + */ +public interface SoaDMU { + HouseholdIf getHouseholdObject(); +} diff --git a/src/java/com/pb/models/ctrampIf/StopDCSoaDMU.java b/src/java/com/pb/models/ctrampIf/StopDCSoaDMU.java new file mode 100644 index 0000000..3bc195c --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/StopDCSoaDMU.java @@ -0,0 +1,153 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +/** + * @author crf
+ * Started: Nov 14, 2008 3:32:58 PM + */ +public class StopDCSoaDMU implements SoaDMU, Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(StopDCSoaDMU.class); + + protected HashMap methodIndexMap; + + private HouseholdIf hh; + protected TourIf tour; + + private int inboundStop; + private int kidsPresent; + protected IndexValues dmuIndex = null; + private double[] logSizeTerms; + + protected int[] altToZone; + protected int[] altToSubZone; + + private TazDataIf tazDataManager; + private ModelStructure modelStructure; + + public StopDCSoaDMU(TazDataIf tazDataManager, ModelStructure modelStructure){ + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + altToZone = tazDataManager.getAltToZoneArray(); + altToSubZone = tazDataManager.getAltToSubZoneArray(); + dmuIndex = new IndexValues(); + } + + public void setDmuState(int zoneId, int stopOriginTaz, int tourDest, HouseholdIf hh, TourIf tour, boolean inboundStop, boolean kidsPresent, double[] logSizeTerms) { + this.hh = hh; + this.tour = tour; + //set index values + dmuIndex.setHHIndex(hh.getHhId()); + dmuIndex.setZoneIndex(zoneId); + dmuIndex.setOriginZone(stopOriginTaz); + dmuIndex.setDestZone( tourDest ); + dmuIndex.setDebug( hh.getDebugChoiceModels() ); + this.inboundStop = inboundStop ? 1 : 0; + this.kidsPresent = kidsPresent ? 1 : 0; + this.logSizeTerms = logSizeTerms; + } + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + public int getInbound() { + return inboundStop; + } + + public int getTourIsJoint() { + return tour.getTourCategoryIsJointNonMandatory() ? 1 : 0; + } + + public int getKidsPresent() { + return kidsPresent; + } + + public int getTourOriginZone() { + return tour.getTourOrigTaz(); + } + + public int getTourDestZone() { + return tour.getTourDestTaz(); + } + + public int getTourModeIsWalk() { + boolean tourModeIsWalk = modelStructure.getTourModeIsWalk( tour.getTourModeChoice() ); + return tourModeIsWalk ? 1 : 0; + } + + public int getTourModeIsBike() { + boolean tourModeIsBike = modelStructure.getTourModeIsBike( tour.getTourModeChoice() ); + return tourModeIsBike ? 1 : 0; + } + + + public int getTourModeIsWalkLocal() { + boolean tourModeIsWalkLocal = modelStructure.getTourModeIsWalkLocal( tour.getTourModeChoice() ); + return tourModeIsWalkLocal ? 1 : 0; + } + + public int getTourModeIsWalkPremium() { + boolean tourModeIsWalkPremium = modelStructure.getTourModeIsWalkPremium( tour.getTourModeChoice() ); + return tourModeIsWalkPremium ? 1 : 0; + } + + public int getTourModeIsWalkTransit() { + boolean tourModeIsWalkLocal = modelStructure.getTourModeIsWalkLocal( tour.getTourModeChoice() ); + boolean tourModeIsWalkPremium = modelStructure.getTourModeIsWalkPremium( tour.getTourModeChoice() ); + return tourModeIsWalkPremium || tourModeIsWalkLocal ? 1 : 0; + } + + public int getTourModeIsDriveTransit() { + boolean tourModeIsDriveTransit = modelStructure.getTourModeIsDriveTransit( tour.getTourModeChoice() ); + return tourModeIsDriveTransit ? 1 : 0; + } + + + public double getLnStopDcSizeAlt(int alt) { + return logSizeTerms[alt]; + } + + public int getStopDestAreaTypeAlt(int alt) { + int[] at = tazDataManager.getZonalAreaType(); + return at[altToZone[alt]-1]; + } + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/StopDestChoiceSize.java b/src/java/com/pb/models/ctrampIf/StopDestChoiceSize.java new file mode 100644 index 0000000..e8fa711 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/StopDestChoiceSize.java @@ -0,0 +1,172 @@ +package com.pb.models.ctrampIf; + +import com.pb.common.datafile.TableDataSet; +import com.pb.common.datafile.CSVFileReader; +import com.pb.models.ctrampIf.jppf.CtrampApplication; + +import java.util.*; +import java.io.File; +import java.io.Serializable; + +import org.apache.log4j.Logger; + +/** + * @author crf
+ * Started: Nov 15, 2008 4:17:57 PM + */ +public class StopDestChoiceSize implements Serializable { + + private transient Logger logger = Logger.getLogger(StopDestChoiceSize.class); + + public static final String PROPERTIES_STOP_DC_SIZE_INPUT = "StopDestinationChoice.SizeCoefficients.InputFile"; + + + private final Map>> sizeMap; //map of purpose,purpose segment, and zone/subzone to size + private final TazDataIf tazDataManager; + private final ModelStructure modelStructure; + private Map>> sizeCoefficients; + + public StopDestChoiceSize( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure ) { + this.tazDataManager = tazDataManager; + this.modelStructure = modelStructure; + sizeMap = new HashMap>>(); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String coeffsFileName = propertyMap.get( PROPERTIES_STOP_DC_SIZE_INPUT ); + coeffsFileName = projectDirectory + coeffsFileName; + + loadSizeData( coeffsFileName ); + } + + public double getDcSize(String purpose, String purposeSegment, int zone, int subzone) { + return sizeMap.get(purpose).get(purposeSegment).get(getZoneSubzoneMapping(zone,subzone)); + } + + private int getZoneSubzoneMapping(int zone, int subzone) { + return zone*10 + subzone; + } + + private void loadSizeData( String coeffsFileName ) { + loadSizeCoefficientTableInformation( readSizeCoefficientTable( coeffsFileName ) ); + determineSizeCoefficients(); + } + + private TableDataSet readSizeCoefficientTable( String coeffsFileName ) { + try{ + CSVFileReader reader = new CSVFileReader(); + return reader.readFile( + new File( coeffsFileName ) + ); + } + catch(Exception e){ + logger.fatal( String.format( "Exception occurred reading DC Stop Size coefficients data file = %s.", coeffsFileName ), e); + throw new RuntimeException(); + } + } + + private Set getValidPurposes() { + Set validPurposes = new HashSet(); + validPurposes.add(modelStructure.WORK_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.ESCORT_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.SHOPPING_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.EAT_OUT_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.OTH_MAINT_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.SOCIAL_PURPOSE_NAME.toLowerCase()); + validPurposes.add(modelStructure.OTH_DISCR_PURPOSE_NAME.toLowerCase()); + return validPurposes; + } + + private Set getValidSegments(String purpose) { + Set validSegments = new HashSet(); + validSegments.add(purpose); + if (purpose.equals(modelStructure.ESCORT_PURPOSE_NAME.toLowerCase()) & modelStructure.getNumEscortSegments() > 0) + for (String segment : modelStructure.ESCORT_SEGMENT_NAMES) + validSegments.add(segment.toLowerCase()); + return validSegments; + } + + private void loadSizeCoefficientTableInformation(TableDataSet coefficients) { + Set sizeTazColumns = new HashSet(); + String[] coefficientTableColumns = coefficients.getColumnLabels(); + String purposeColumn = modelStructure.getDcSizeCoeffPurposeFieldName(); + String segmentColumn = modelStructure.getDcSizeCoeffSegmentFieldName(); + boolean foundPurposeColumn = false; + boolean foundSegmentColumn = false; + boolean errors = false; + for(String label : coefficientTableColumns) { + if (label.equals(purposeColumn)) { + foundPurposeColumn = true; + continue; + } + if (label.equals(segmentColumn)) { + foundSegmentColumn = true; + continue; + } + + if (!tazDataManager.isValidZoneTableField(label)) { + logger.fatal("Stop size coefficient table column does not correspond to taz data column: " + label); + errors = true; + } + sizeTazColumns.add(label); + } + if (!foundPurposeColumn) { + logger.fatal("Purpose column (" + purposeColumn + ") not found in stop size coefficient table"); + errors = true; + } + if (!foundSegmentColumn) { + logger.fatal("Purpose segment column (" + segmentColumn + ") not found in stop size coefficient table"); + errors = true; + } + + if (!errors) { + sizeCoefficients = new HashMap>>(); + Set validPurposes = getValidPurposes(); + for (int i = 1; i <= coefficients.getRowCount(); i++) { + String purpose = coefficients.getStringValueAt(i,purposeColumn).toLowerCase(); + String segment = coefficients.getStringValueAt(i,segmentColumn).toLowerCase(); + if (validPurposes.contains(purpose)) { + if (!sizeCoefficients.containsKey(purpose)) + sizeCoefficients.put(purpose,new HashMap>()); + if (getValidSegments(purpose).contains(segment)) { + Map coefficientMap = new HashMap(); + for (String column : sizeTazColumns) + coefficientMap.put(column,(double) coefficients.getValueAt(i,column)); + sizeCoefficients.get(purpose).put(segment,coefficientMap); + } else { + logger.fatal("Invalid segment for purpose " + purpose + " found in stop destination choice size coefficient table: " + segment); + errors = true; + } + + } else { + logger.fatal("Invalid purpose found in stop destination choice size coefficient table: " + purpose); + errors = true; + } + } + } + + + if (errors) { + throw new RuntimeException("Errors in stop destination choice size coefficient file; see log file for details."); + } + } + + private void determineSizeCoefficients() { + sizeMap.clear(); + for (String purpose : sizeCoefficients.keySet()) { + sizeMap.put(purpose,new HashMap>()); + for (String segment : sizeCoefficients.get(purpose).keySet()) { + Map zoneSizeMap = new HashMap(); + for (int i = 1; i <= tazDataManager.getNumberOfZones(); i++) { + double size = 0.0d; + Map coefficients = sizeCoefficients.get(purpose).get(segment); + for (String column : sizeCoefficients.get(purpose).get(segment).keySet()) + size += tazDataManager.getZoneTableValue(i,column)*coefficients.get(column); + double[] walkPercentages = tazDataManager.getZonalWalkPercentagesForTaz(i); + for (int j = 0; j < tazDataManager.getNumberOfSubZones(); j++) + zoneSizeMap.put(getZoneSubzoneMapping(i,j),size*walkPercentages[j]); + } + sizeMap.get(purpose).put(segment,zoneSizeMap); + } + } + } +} diff --git a/src/java/com/pb/models/ctrampIf/StopFrequencyDMU.java b/src/java/com/pb/models/ctrampIf/StopFrequencyDMU.java new file mode 100644 index 0000000..416b1dc --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/StopFrequencyDMU.java @@ -0,0 +1,390 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +import org.apache.log4j.Logger; + +/** + * This class is used for ... + * + * @author Christi Willison + * @version Nov 4, 2008 + *

+ * Created by IntelliJ IDEA. + */ +public class StopFrequencyDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(StopFrequencyDMU.class); + + protected HashMap methodIndexMap; + + + // TODO: need to set/get these values from some generic structure object that was set by project specific code. + private static final int START_AM_PEAK = 6; + private static final int END_AM_PEAK = 9; + private static final int START_PM_PEAK = 16; + private static final int END_PM_PEAK = 19; + + public static final int[] NUM_OB_STOPS_FOR_ALT = { -99999999, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 }; + public static final int[] NUM_IB_STOPS_FOR_ALT = { -99999999, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 }; + + private ModelStructure modelStructure; + + + protected IndexValues dmuIndex; + protected HouseholdIf household; + protected PersonIf person; + protected TourIf tour; + + private int originTazAreaType; + private int destinationTazAreaType; + private float[] pkTransitRetailAccessibility; + private float[] opTransitRetailAccessibility; + private float[] nonMotorRetailAccessibility; + + + public StopFrequencyDMU( ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + } + + public void setDmuIndexValues( int hhid, int homeTaz, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhid ); + dmuIndex.setZoneIndex( homeTaz ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( household.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug SF UEC" ); + } + + } + + public void setHouseholdObject ( HouseholdIf household) { + this.household = household; + } + + public void setPersonObject ( PersonIf person ) { + this.person = person; + } + + public void setTourObject ( TourIf tour ) { + this.tour = tour; + } + + public void setOriginTazAreaType( int at ) { + originTazAreaType = at; + } + + public void setDestTazAreaType( int at ) { + destinationTazAreaType = at; + } + + public void setZonalAccessibilities( float[] pkTransitRetailAccessibility, float[] opTransitRetailAccessibility, float[] nonMotorRetailAccessibility ) { + this.pkTransitRetailAccessibility = pkTransitRetailAccessibility; + this.opTransitRetailAccessibility = opTransitRetailAccessibility; + this.nonMotorRetailAccessibility = nonMotorRetailAccessibility; + } + + + + public IndexValues getDmuIndexValues(){ + return dmuIndex; + } + + public int getOriginAreaType() { + return originTazAreaType; + } + + public int getDestinationAreaType() { + return destinationTazAreaType; + } + + public int getIncomeInDollars() { + return household.getIncomeInDollars(); + } + + public int getNumPersons() { + return household.getHhSize(); + } + + public int getNumFullWork() { + return household.getNumFtWorkers(); + } + + public int getNumStudent() { + return household.getNumStudents(); + } + + public int getNumVeh() { + return household.getAutoOwnershipModelResult(); + } + + public int getCarSuff() { + int returnValue = 0; + int numCars = household.getAutoOwnershipModelResult(); + int numWorkers = household.getNumFtWorkers() + household.getNumPtWorkers(); + if ( numCars >= numWorkers ) + returnValue = 1; + return returnValue; + } + + public int getNAge0to4() { + return household.getNumPersons0to4(); + } + + public int getNAge5to15() { + return household.getNumPersons5to15(); + } + + public int getNAdult() { + // method getDrivers() returns the number of people 16+ in the household + return household.getDrivers(); + } + + public int getGenderIsFemale() { + return person.getPersonIsFemale(); + } + + public int getStartTime() { + return tour.getTourDepartPeriod(); + } + + public int getEndTime() { + return tour.getTourArrivePeriod(); + } + + /** + * count the number of subtours assoctiated with this work tour + * @return + */ + public int getNumAtWorkSubTours() { + int numSubTours = 0; + for ( TourIf subTour : person.getListOfAtWorkSubtours() ) { + int subtourWorkIndex = subTour.getWorkTourIndexFromSubtourId( subTour.getTourId() ); + + // count this subtour if its work tour is the current tour + if ( subtourWorkIndex == tour.getTourId() ) + numSubTours++; + } + return numSubTours; + } + + public int getNumWorkTours() { + return person.getNumWorkTours(); + } + + public int getNumUnivTours() { + return person.getNumUniversityTours(); + } + + public int getNumSchoolTours() { + return person.getNumSchoolTours(); + } + + public int getNumEscortTours() { + return person.getNumIndividualEscortTours(); + } + + /** + * @return number of total (individual and joint) shopping tours by household members + */ + public int getNumHShopTours() { + int numShopTours = 0; + + // add up total individual shopping tours + PersonIf[] persons = household.getPersons(); + for ( int i=1; i < persons.length; i++ ) + numShopTours += persons[i].getNumIndividualShoppingTours(); + + // add in any joint shopping tours + TourIf[] jointTours = household.getJointTourArray(); + if ( jointTours != null ) { + for ( TourIf t : jointTours ) { + if ( t.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.SHOPPING_PURPOSE_NAME ) ) + numShopTours++; + } + } + + return numShopTours; + } + + public int getNumShopTours() { + return person.getNumIndividualShoppingTours(); + } + + /** + * @return number of total (individual and joint) maintenance tours by household members + */ + public int getNumHMaintTours() { + int numMaintTours = 0; + + // add up total individual maintenance tours + PersonIf[] persons = household.getPersons(); + for ( int i=1; i < persons.length; i++ ) + numMaintTours += persons[i].getNumIndividualOthMaintTours(); + + // add in any joint maintenance tours + TourIf[] jointTours = household.getJointTourArray(); + if ( jointTours != null ) { + for ( TourIf t : jointTours ) { + if ( t.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.OTH_MAINT_PURPOSE_NAME ) ) + numMaintTours++; + } + } + + return numMaintTours; + } + + public int getNumMaintTours() { + return person.getNumIndividualOthMaintTours(); + } + + public int getNumEatOutTours() { + return person.getNumIndividualEatOutTours(); + } + + public int getNumVisitTours() { + return person.getNumIndividualSocialTours(); + } + + public int getTourIsJoint() { + return tour.getTourCategoryIsJointNonMandatory() ? 1 : 0; + } + + public int getTourIsVisit() { + return tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.SOCIAL_PURPOSE_NAME ) ? 1 : 0; + } + + public int getNumPersonsInJointTour() { + int num = 0; + if ( tour.getTourCategoryIsJointNonMandatory() ) + num = tour.getPersonNumArray().length; + return num; + } + + public int getJointTourHasAdultsOnly() { + return tour.getJointTourComposition() == JointTourFrequencyModel.JOINT_TOUR_COMPOSITION_ADULTS ? 1 : 0; + } + + public int getTourModeIsTransit() { + boolean tourModeIsTransit = modelStructure.getTourModeIsTransit( tour.getTourModeChoice() ); + return tourModeIsTransit ? 1 : 0; + } + + public int getTourModeIsDriveTransit() { + boolean tourModeIsDriveTransit = modelStructure.getTourModeIsDriveTransit( tour.getTourModeChoice() ); + return tourModeIsDriveTransit ? 1 : 0; + } + + public int getTourModeIsSchoolBus() { + boolean tourModeIsSchoolBus = modelStructure.getTourModeIsSchoolBus( tour.getTourModeChoice() ); + return tourModeIsSchoolBus ? 1 : 0; + } + + public int getTourModeIsNonMotorized() { + boolean tourModeIsNonMotorized = modelStructure.getTourModeIsNonMotorized( tour.getTourModeChoice() ); + return tourModeIsNonMotorized ? 1 : 0; + } + + public double getAccesibilityAtDestination() { + + double returnValue = 0.0; + int destinationTaz = dmuIndex.getOriginZone(); + + if ( getTourModeIsTransit() == 1 ) + if ( tourStartsInPeakPeriod() ) + returnValue = pkTransitRetailAccessibility[destinationTaz]; + else + returnValue = opTransitRetailAccessibility[destinationTaz]; + else if ( getTourModeIsNonMotorized() == 1 ) + returnValue = nonMotorRetailAccessibility[destinationTaz]; + + return returnValue; + } + + public double getAccesibilityAtOrigin() { + + double returnValue = 0.0; + int originTaz = dmuIndex.getOriginZone(); + + if ( getTourModeIsTransit() == 1 ) + if ( tourStartsInPeakPeriod() ) + returnValue = pkTransitRetailAccessibility[originTaz]; + else + returnValue = opTransitRetailAccessibility[originTaz]; + else if ( getTourModeIsNonMotorized() == 1 ) + returnValue = nonMotorRetailAccessibility[originTaz]; + + return returnValue; + } + + + private boolean tourStartsInPeakPeriod() { + + boolean returnValue = false; + if ( ( tour.getTourDepartPeriod() >= START_AM_PEAK && tour.getTourDepartPeriod() <= END_AM_PEAK ) || + ( tour.getTourDepartPeriod() >= START_PM_PEAK && tour.getTourDepartPeriod() <= END_PM_PEAK ) ) { + returnValue = true; + } + return returnValue; + } + + + + public int getNumStopsAlt(int alt){ + int obStops = NUM_OB_STOPS_FOR_ALT[alt]; + int ibStops = NUM_IB_STOPS_FOR_ALT[alt]; + return obStops + ibStops; + } + + + public int getNumIbStopsAlt(int alt){ + return NUM_IB_STOPS_FOR_ALT[alt]; + } + + + public int getNumObStopsAlt(int alt){ + return NUM_OB_STOPS_FOR_ALT[alt]; + } + + + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/StopIf.java b/src/java/com/pb/models/ctrampIf/StopIf.java new file mode 100644 index 0000000..762d049 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/StopIf.java @@ -0,0 +1,60 @@ +package com.pb.models.ctrampIf; + +import org.apache.log4j.Logger; + +public interface StopIf +{ + + public abstract void setOrig(int orig); + + public abstract void setDest(int dest); + + public abstract void setPark(int park); + + public abstract void setMode(int mode); + + public abstract void setStopPeriod(int period); + + public abstract int getOrig(); + + public abstract int getDest(); + + public abstract int getPark(); + + public abstract int getOrigWalkSegment(); + + public abstract void setOrigWalkSegment(int origWalkSegment); + + public abstract int getDestWalkSegment(); + + public abstract void setDestWalkSegment(int destWalkSegment); + + public abstract String getOrigPurpose(); + + public abstract String getDestPurpose(); + + public abstract int getDestPurposeIndex(); + + public abstract int getMode(); + + public abstract int getTourDepartPeriod(); + + public abstract int getStopPeriod(); + + public abstract TourIf getTour(); + + public abstract boolean isInboundStop(); + + public abstract int getStopId(); + + public abstract void logStopObject( Logger logger, int numChars ); + + public abstract void setBTap(int tap); + + public abstract void setATap(int tap); + + public abstract int getBTap(); + + public abstract int getATap(); + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/StopLocationDMU.java b/src/java/com/pb/models/ctrampIf/StopLocationDMU.java new file mode 100644 index 0000000..edaad24 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/StopLocationDMU.java @@ -0,0 +1,244 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +/** + * This class is used for ... + * + * @author Christi Willison + * @version Nov 4, 2008 + *

+ * Created by IntelliJ IDEA. + */ +public class StopLocationDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(StopLocationDMU.class); + + public HashMap methodIndexMap; + + public IndexValues dmuIndex; + public HouseholdIf household; + public PersonIf person; + public TourIf tour; + public StopIf stop; + + + public int[] altToZone; + public int[] altToSubZone; + + // mode choice logsums for stop origin to stop destination alternatives + public double[][] mcLogsumsIk; + // mode choice logsums for stop destination apublices to tour primary destination + public double[][] mcLogsumsKj; + + public double[][] dcSoaCorrections; + private double[] logSizeTerms; + + private int stopNumber = -1; + private int inboundStop = -1; + + private TazDataIf tazDataManager; + + public StopLocationDMU(TazDataIf tazDataManager, ModelStructure modelStructure){ + dmuIndex = new IndexValues(); + + altToZone = tazDataManager.getAltToZoneArray(); + altToSubZone = tazDataManager.getAltToSubZoneArray(); + + + int numZones = tazDataManager.getNumberOfZones(); + int numSubZones = tazDataManager.getNumberOfSubZones(); + + mcLogsumsIk = new double[numZones+1][numSubZones]; + mcLogsumsKj = new double[numZones+1][numSubZones]; + dcSoaCorrections = new double[numZones+1][numSubZones]; + + this.tazDataManager = tazDataManager; + } + + + public void setDmuIndexValues( int hhid, int homeTaz, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhid ); + dmuIndex.setZoneIndex( homeTaz ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone(destTaz); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( household.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug SL UEC" ); + } + + } + + public void setDcSoaCorrections( int zone, int subzone, double correction ){ + dcSoaCorrections[zone][subzone] = correction; + } + + public void setTripMcLogsumIk( int zone, int subzone, double logsum ){ + mcLogsumsIk[zone][subzone] = logsum; + } + + public void setTripMcLogsumKj( int zone, int subzone, double logsum ){ + mcLogsumsKj[zone][subzone] = logsum; + } + + public void setLogSizeTerms( double[] stopLocSize ){ + logSizeTerms = stopLocSize; + } + + public double getDcSoaCorrectionsAlt( int alt ){ + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + return dcSoaCorrections[zone][subzone]; + } + + public double getTripModeChoiceLogsumOrigToStopAlt( int alt ) { + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + return mcLogsumsIk[zone][subzone]; + } + + public double getTripModeChoiceLogsumStopAltToDest( int alt ) { + int zone = altToZone[alt]; + int subzone = altToSubZone[alt]; + return mcLogsumsKj[zone][subzone]; + } + + public int getStopDestAreaTypeAlt(int alt) { + int[] at = tazDataManager.getZonalAreaType(); + return at[altToZone[alt]-1]; + } + + public double getLnStopDcSizeAlt( int alt ) { + return logSizeTerms[alt]; + } + + public void setHouseholdObject ( HouseholdIf household) { + this.household = household; + } + + public void setPersonObject ( PersonIf person ) { + this.person = person; + } + + public void setTourObject(TourIf tour) { + this.tour = tour; + } + + public void setStopObject(StopIf stop) { + this.stop = stop; + } + + public HouseholdIf getHouseholdObject() { + return household; + } + + public PersonIf getPersonObject() { + return person; + } + + public IndexValues getDmuIndexValues(){ + return dmuIndex; + } + + public int getTourIsJoint() { + return tour.getTourCategoryIsJointNonMandatory() ? 1 : 0; + } + + + public int getStopPurposeIsWork() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.WORK_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsEscort() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.ESCORT_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsShopping() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.SHOPPING_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsEatOut() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.EAT_OUT_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsOthMaint() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.OTH_MAINT_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsSocial() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.SOCIAL_PURPOSE_NAME ) ? 1 : 0; + } + + public int getStopPurposeIsOthDiscr() { + return stop.getDestPurpose().equalsIgnoreCase( ModelStructure.OTH_DISCR_PURPOSE_NAME ) ? 1 : 0; + } + + + public int getTourOriginZone() { + return tour.getTourOrigTaz(); + } + + public int getTourDestZone() { + return tour.getTourDestTaz(); + } + + public int getTourMode() { + return tour.getTourModeChoice(); + } + + public int getStopNumber() { + return stopNumber; + } + + public int getInboundStop() { + return inboundStop; + } + + public void setStopNumber(int stopNumber) { + this.stopNumber = stopNumber; + } + + public void setInboundStop(boolean inboundStop) { + this.inboundStop = inboundStop ? 1 : 0; + } + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/TazDataHandler.java b/src/java/com/pb/models/ctrampIf/TazDataHandler.java new file mode 100644 index 0000000..99c5d88 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TazDataHandler.java @@ -0,0 +1,810 @@ +package com.pb.models.ctrampIf; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.ResourceBundle; + +import org.apache.log4j.Logger; + +import com.pb.cmap.tvpb.MazTapTazData; +import com.pb.common.datafile.OLD_CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.util.ResourceUtil; + + +/** + * This class provides methods defined in the TazDataIf interface for accessing zonal data stored in + * its TazDataManager object. + * + * A CT-RAMP tour based model application could create an instance of a subclass of this class, where additional + * project specific varaible definitions and methods are defined and pass that instance to its model + * component objects. + * + * Alternatively, an application could use TazDataHandlerRmi as the base class instead and create a "remoteable" subclass. + * The TazDataHandlerRmi class implements the same interface, so the model component classes can be unaware of whether the + * taz data handler object accesses zonal data from its member object or remotely from a server. Those methods in the + * rmi class access zonal data from a TazDataManager object contained in a "taz data server" object which must exist in + * a separate JVM on the same machine or on another addressable machine over the network. + * + * The flexibility provided by this design is intended to allow the "local" instance to be declared and passed within a single JVM + * to model components for possibly greater performance (yet to be tested and proven) at production run time. + * The "rmi" instance however allows the model components to access zonal data from a "long-running process" (the server + * class may execute for weeks or months). This approach aids in model development as during development, model + * applications can be written to skip startup procedures for reading zonal data, and access them directly from the + * server that is already running. + * + * A similar approach is planned for managing objects such as Household objects and ModelResults objects so that model + * components, for example individual non-mandatory tour related models which occur well into the tour based model stream, + * can be run in a "hot-start" fasion, where the model component of interest is executed immediately where all the + * preliminary data and prior model results it requires are stored in long-running server objects. Testing and debugging + * of these model components can occur without the time required to run through all preliminary steps. + * + * + */ + +public class TazDataHandler implements TazDataIf, Serializable { + + protected transient Logger logger = Logger.getLogger(TazDataHandler.class); + + public static final String PROPERTIES_TAZ_DATA = "TazData.File"; + public static final String PROPERTIES_TAZ_DATA_FIELD_NAME = "TazData.File.Field.Name"; + public static final String PROPERTIES_ZONAL_ACCESSIBILITIESS_DATA = "ZonalAccessibilities.file"; + public static final String PROPERTIES_ZONAL_ACCESSIBILITIESS_DATA_FIELD_NAME = "ZonalAccessibilities.Field.Name"; + + // default values - can be overridden by subclass setter methods + private static final String ZONE_DATA_ZONE_FIELD_NAME = "maz"; + private static final String ZONE_DATA_AREATYPE_FIELD_NAME = "at"; + private static final String ZONE_DATA_DISTRICT_FIELD_NAME = "dist"; + private static final String ZONE_DATA_COUNTY_FIELD_NAME = "county"; + private static final String ZONE_DATA_GRADESCHOOL_DISTRICT_FIELD_NAME = "gradeschool"; + private static final String ZONE_DATA_HIGHSCHOOL_DISTRICT__FIELD_NAME = "highschool"; + + private static final String ZONE_DATA_PARKTOT_FIELD_NAME = "parkTot"; + private static final String ZONE_DATA_PARKLNG_FIELD_NAME = "parkLong"; + private static final String ZONE_DATA_PROPFREE_FIELD_NAME = "PropFree"; + private static final String ZONE_DATA_PARKRATE_FIELD_NAME = "ParkRate"; + + private static final String ZONE_DATA_BHHDEN_FIELD_NAME = "b_hhden"; + private static final String ZONE_DATA_BEMPDEN_FIELD_NAME = "b_empden"; + private static final String ZONE_DATA_PEF_FIELD_NAME = "pef"; + private static final String ZONE_DATA_RING_FIELD_NAME = "ring"; + + private static final String ACCESSIBILITIES_FILE_ZONE_FIELD_NAME = "maz"; + private static final String ACCESSIBILITIES_PEAK_AUTO_RETAIL_FIELD_NAME = "autoPeakRetail"; + private static final String ACCESSIBILITIES_PEAK_AUTO_TOTAL_FIELD_NAME = "autoPeakTotal"; + private static final String ACCESSIBILITIES_PEAK_TRANSIT_RETAIL_FIELD_NAME = "transitPeakRetail"; + private static final String ACCESSIBILITIES_PEAK_TRANSIT_TOTAL_FIELD_NAME = "transitPeakTotal"; + private static final String ACCESSIBILITIES_OFF_PEAK_AUTO_RETAIL_FIELD_NAME = "autoOffPeakRetail"; + private static final String ACCESSIBILITIES_OFF_PEAK_AUTO_TOTAL_FIELD_NAME = "autoOffPeakTotal"; + private static final String ACCESSIBILITIES_OFF_PEAK_TRANSIT_RETAIL_FIELD_NAME = "transitOffPeakRetail"; + private static final String ACCESSIBILITIES_OFF_PEAK_TRANSIT_TOTAL_FIELD_NAME = "transitOffPeakTotal"; + private static final String ACCESSIBILITIES_NON_MOTORIZED_RETAIL_FIELD_NAME = "nonMotorizedRetail"; + private static final String ACCESSIBILITIES_NON_MOTORIZED_TOTAL_FIELD_NAME = "nonMotorizedTotal"; + private static final String ACCESSIBILITIES_17_FIELD_NAME = "access17"; + private static final String ACCESSIBILITIES_18_FIELD_NAME = "access18"; + + private static final String[] SUB_ZONE_NAMES = { "all"}; //1 subzone now + + protected String projectDirectory; + protected String tazDataFileName; + + protected int cbdAreaTypesArrayIndex; + protected int urbanAreaTypesArrayIndex; + protected int suburbanAreaTypesArrayIndex; + protected int ruralAreaTypesArrayIndex; + protected int[][] areaTypes; + + private int NUM_ZONES; + private int NUM_SUBZONES; + + private float[] pkAutoRetail; + private float[] pkAutoTotal; + private float[] opAutoRetail; + private float[] opAutoTotal; + private float[] pkTransitRetail; + private float[] pkTransitTotal; + private float[] opTransitRetail; + private float[] opTransitTotal; + private float[] nonMotorizedRetail; + private float[] nonMotorizedTotal; + private float[] access17; + private float[] access18; + private float[] bhhden; + private float[] bempden; + private float[] pef; + private int[] ring; + + protected String tazDataZoneFieldName = ""; + protected String tazDataDistFieldName= ""; + protected String tazDataCountyFieldName= ""; + protected String tazDataAtFieldName= ""; + protected String parkTotFieldName= ""; + protected String parkLongFieldName= ""; + protected String propFreeFieldName= ""; + protected String parkRateFieldName= ""; + protected String tazDataGradeSchoolFieldName= ""; + protected String tazDataHighSchoolFieldName= ""; + protected String bhhdenFieldName = ""; + protected String bempdenFieldName = ""; + protected String pefFieldName = ""; + protected String ringFieldName = ""; + + + protected String zonalAccessibilityFileName; + protected String zonalAccessibilityFieldName; + + protected TableDataSet zoneDataTable; + + + // zoneTableRow is a correspondence between zone number (i,e, origin taz or dest taz) and the TableDataSet row + // in which those zonal attributes are stored. + protected int[] zoneTableRow; + + // indexToZone is a correspondence between 1-based zone index values (1,...,numZones) and the zone values. + protected int[] indexToZone; + + // altToZone is a correspondence between DC alternative number (1,...,numZones*numSubzones) and 1-based zone index (1,...,numZones) + protected int[] altToZone; + + // altToSubZone is a correspondence between DC alternative number (1,...,numZones*numSubzones) and 0-based subzone index (0,...,numSubZones-1) + protected int[] altToSubZone; + + // 1st dimension is indexed by zone number, 2nd dimension is walk segments - 1 walk segment now + protected float[][] zonalWalkPctArray; + + protected String[] subZoneNames; + + public TazDataHandler( ResourceBundle rb, String projectDirectory ){ + + this.projectDirectory = projectDirectory; + + tazDataZoneFieldName = ZONE_DATA_ZONE_FIELD_NAME; + tazDataAtFieldName = ZONE_DATA_AREATYPE_FIELD_NAME; + tazDataDistFieldName = ZONE_DATA_DISTRICT_FIELD_NAME; + tazDataCountyFieldName = ZONE_DATA_COUNTY_FIELD_NAME; + parkTotFieldName = ZONE_DATA_PARKTOT_FIELD_NAME; + parkLongFieldName = ZONE_DATA_PARKLNG_FIELD_NAME; + propFreeFieldName = ZONE_DATA_PROPFREE_FIELD_NAME; + parkRateFieldName = ZONE_DATA_PARKRATE_FIELD_NAME; + tazDataGradeSchoolFieldName = ZONE_DATA_GRADESCHOOL_DISTRICT_FIELD_NAME; + tazDataHighSchoolFieldName = ZONE_DATA_HIGHSCHOOL_DISTRICT__FIELD_NAME; + bhhdenFieldName = ZONE_DATA_BHHDEN_FIELD_NAME; + bempdenFieldName = ZONE_DATA_BEMPDEN_FIELD_NAME; + pefFieldName = ZONE_DATA_PEF_FIELD_NAME; + ringFieldName = ZONE_DATA_RING_FIELD_NAME; + + subZoneNames = SUB_ZONE_NAMES; + + // locate the taz data from the .properties file + tazDataFileName = projectDirectory + ResourceUtil.getProperty(rb, PROPERTIES_TAZ_DATA); + tazDataZoneFieldName = ResourceUtil.getProperty(rb, PROPERTIES_TAZ_DATA_FIELD_NAME); + + // locate the walk percentages data from the .properties file + zonalAccessibilityFileName = projectDirectory + ResourceUtil.getProperty(rb, PROPERTIES_ZONAL_ACCESSIBILITIESS_DATA); + zonalAccessibilityFieldName = ResourceUtil.getProperty(rb, PROPERTIES_ZONAL_ACCESSIBILITIESS_DATA_FIELD_NAME); + + } + + public void setupTazDataManager() { + + // create the zonal data table + zoneDataTable = readZonalData(tazDataFileName); + + // compute the number of destination choice alternatives + NUM_SUBZONES = subZoneNames.length; + + // prepare the zonal walk percent array - 1 subzone type now 100% coverage + zonalWalkPctArray = new float[NUM_SUBZONES][NUM_ZONES + 1]; + Arrays.fill(zonalWalkPctArray[0], 1.0f); + + // dimension the correspondence arrays that will contain the zone and subzone, respectively, given the DC alternative index (1,...,numAlts) + altToZone = new int[NUM_ZONES*NUM_SUBZONES + 1]; + altToSubZone = new int[NUM_ZONES*NUM_SUBZONES + 1]; + + for (int i=1; i <= NUM_ZONES*NUM_SUBZONES; i++) { + altToZone[i] = getZoneFromAlt(i); + altToSubZone[i] = getWalkSubzoneFromAlt(i); + } + + + readZonalAccessibilitiesFile (zonalAccessibilityFileName); + } + + + + private TableDataSet readZonalData(String zoneDataFileName) { + + int numZones = 0; + int maxZone = 0; + int zoneCol; + TableDataSet zoneTable; + + try{ + + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + reader.setDelimSet( "," + reader.getDelimSet() ); + zoneTable = reader.readFile(new File( zoneDataFileName )); + + // set global max zone and num zones values, and make sure there are no duplicates. + zoneCol = zoneTable.getColumnPosition( tazDataZoneFieldName ); + HashMap zoneValues = new HashMap(); + + for (int i=1; i <= zoneTable.getRowCount(); i++) { + int zone = (int)zoneTable.getValueAt(i, zoneCol); + if ( zoneValues.containsKey( zone ) ) { + logger.fatal( String.format("zone employment table read from %s has duplicate value for ZONE=%d in column %d at record number %d", zoneDataFileName, zone, zoneCol, (i+1)) ); + throw new RuntimeException(); + } + else { + zoneValues.put(zone, i); + numZones++; + if ( zone > maxZone ) + maxZone = zone; + } + + } + + } + catch(IOException e){ + logger.error( String.format( "Exception occurred reading zonal employment data file: %s into TableDataSet object.", zoneDataFileName ) ); + throw new RuntimeException(); + } + + NUM_ZONES = numZones; + + // store the row numbers for each zone so that zonal attributes can be retrieved later using given a zone number + indexToZone = new int[numZones+1]; + zoneTableRow = new int[maxZone+1]; + for (int i=1; i <= zoneTable.getRowCount(); i++) { + int zone = (int)zoneTable.getValueAt(i, zoneCol); + zoneTableRow[zone] = i; + indexToZone[i] = zone; + } + + return zoneTable; + + } + + + private void readZonalAccessibilitiesFile (String fileName) { + + pkAutoRetail = new float[NUM_ZONES + 1]; + pkAutoTotal = new float[NUM_ZONES + 1]; + opAutoRetail = new float[NUM_ZONES + 1]; + opAutoTotal = new float[NUM_ZONES + 1]; + pkTransitRetail = new float[NUM_ZONES + 1]; + pkTransitTotal = new float[NUM_ZONES + 1]; + opTransitRetail = new float[NUM_ZONES + 1]; + opTransitTotal = new float[NUM_ZONES + 1]; + nonMotorizedRetail = new float[NUM_ZONES + 1]; + nonMotorizedTotal = new float[NUM_ZONES + 1]; + access17 = new float[NUM_ZONES + 1]; + access18 = new float[NUM_ZONES + 1]; + + if (fileName != null) { + + try { + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + reader.setDelimSet( " " + reader.getDelimSet() ); + TableDataSet acc = reader.readFile(new File(fileName)); + + int tazPosition = acc.getColumnPosition( zonalAccessibilityFieldName ); + if (tazPosition <= 0) { + logger.fatal( String.format("expected zone field name=%s was not a field in the zonal accessibilities file: %s.", zonalAccessibilityFieldName, fileName)); + throw new RuntimeException(); + } + + int pkAutoRetailPosition = acc.getColumnPosition( ACCESSIBILITIES_PEAK_AUTO_RETAIL_FIELD_NAME ); + if (pkAutoRetailPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_PEAK_AUTO_RETAIL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int pkAutoTotalPosition = acc.getColumnPosition( ACCESSIBILITIES_PEAK_AUTO_TOTAL_FIELD_NAME ); + if (pkAutoTotalPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_PEAK_AUTO_TOTAL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int pkTransitRetailPosition = acc.getColumnPosition( ACCESSIBILITIES_PEAK_TRANSIT_RETAIL_FIELD_NAME ); + if (pkTransitRetailPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_PEAK_TRANSIT_RETAIL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int pkTransitTotalPosition = acc.getColumnPosition( ACCESSIBILITIES_PEAK_TRANSIT_TOTAL_FIELD_NAME ); + if (pkTransitTotalPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_PEAK_TRANSIT_TOTAL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int opAutoRetailPosition = acc.getColumnPosition( ACCESSIBILITIES_OFF_PEAK_AUTO_RETAIL_FIELD_NAME ); + if (opAutoRetailPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_OFF_PEAK_AUTO_RETAIL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int opAutoTotalPosition = acc.getColumnPosition( ACCESSIBILITIES_OFF_PEAK_AUTO_TOTAL_FIELD_NAME ); + if (opAutoTotalPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_OFF_PEAK_AUTO_TOTAL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int opTransitRetailPosition = acc.getColumnPosition( ACCESSIBILITIES_OFF_PEAK_TRANSIT_RETAIL_FIELD_NAME ); + if (opTransitRetailPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_OFF_PEAK_TRANSIT_RETAIL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int opTransitTotalPosition = acc.getColumnPosition( ACCESSIBILITIES_OFF_PEAK_TRANSIT_TOTAL_FIELD_NAME ); + if (opTransitTotalPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_OFF_PEAK_TRANSIT_TOTAL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int nonMotorizedRetailPosition = acc.getColumnPosition( ACCESSIBILITIES_NON_MOTORIZED_RETAIL_FIELD_NAME ); + if (nonMotorizedRetailPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_NON_MOTORIZED_RETAIL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int nonMotorizedTotalPosition = acc.getColumnPosition( ACCESSIBILITIES_NON_MOTORIZED_TOTAL_FIELD_NAME ); + if (nonMotorizedTotalPosition <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_NON_MOTORIZED_TOTAL_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int access17Position = acc.getColumnPosition( ACCESSIBILITIES_17_FIELD_NAME ); + if (access17Position <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_17_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int access18Position = acc.getColumnPosition( ACCESSIBILITIES_18_FIELD_NAME ); + if (access18Position <= 0) { + logger.fatal( String.format("expected field name=%s was not a field in the zonal accessibilities file: %s.", ACCESSIBILITIES_18_FIELD_NAME, fileName)); + throw new RuntimeException(); + } + + int taz; + for (int i=1; i <= acc.getRowCount(); i++) { + taz = (int) acc.getValueAt(i, tazPosition); + pkAutoRetail[taz] = acc.getValueAt(i, pkAutoRetailPosition); + pkAutoTotal[taz] = acc.getValueAt(i, pkAutoTotalPosition); + pkTransitRetail[taz] = acc.getValueAt(i, pkTransitRetailPosition); + pkTransitTotal[taz] = acc.getValueAt(i, pkTransitTotalPosition); + opAutoRetail[taz] = acc.getValueAt(i, opAutoRetailPosition); + opAutoTotal[taz] = acc.getValueAt(i, opAutoTotalPosition); + opTransitRetail[taz] = acc.getValueAt(i, opTransitRetailPosition); + opTransitTotal[taz] = acc.getValueAt(i, opTransitTotalPosition); + nonMotorizedRetail[taz] = acc.getValueAt(i, nonMotorizedRetailPosition); + nonMotorizedTotal[taz] = acc.getValueAt(i, nonMotorizedTotalPosition); + access17[taz] = acc.getValueAt(i, access17Position); + access18[taz] = acc.getValueAt(i, access18Position); + } + + } + catch (IOException e) { + logger.fatal( String.format("exception caught reading accessibilities file: %s", fileName), e); + } + + } else { + + logger.fatal( "no zonal accessibilities data file was named in properties file with target: " + fileName ); + throw new RuntimeException(); + + } + + } + + + /** + * @param alt is the DC alternaive number + * @return zone number for the DC alt. + */ + private int getZoneFromAlt ( int alt ) { + int zone = (int)((alt-1)/NUM_SUBZONES) + 1; + if ( zone < 1 || zone > NUM_ZONES ) { + logger.fatal( String.format("invalid value for zone index = %d, determined for alt = %d.", zone, alt) ); + logger.fatal( String.format("NUM_ZONES = %d, NUM_SUBZONES = %d.", NUM_ZONES, NUM_SUBZONES) ); + throw new RuntimeException(); + } + return zone; + } + + /** + * @param alt is the DC alternaive number + * @return walk subzone index for the DC alt. + */ + private int getWalkSubzoneFromAlt ( int alt ) { + int zone = getZoneFromAlt ( alt ); + int subzone = alt - (zone-1)*NUM_SUBZONES - 1; + if ( subzone < 0 || subzone >= NUM_SUBZONES ) { + logger.fatal( String.format("invalid value for walk subzone index = %d, zone = %d, determined for alt = %d.", subzone, zone, alt) ); + logger.fatal( String.format("NUM_ZONES = %d, NUM_SUBZONES = %d.", NUM_ZONES, NUM_SUBZONES) ); + throw new RuntimeException(); + } + return subzone; + } + + public String testRemote() { + return String.format("testRemote() method in %s called.", this.getClass().getCanonicalName() ); + } + + public int[] getAltToZoneArray () { + return altToZone; + } + + public int[] getAltToSubZoneArray () { + return altToSubZone; + } + + public int[] getIndexToZoneArray () { + return indexToZone; + } + + public int[] getZoneTableRowArray () { + return zoneTableRow; + } + + + /** + * + * @param field is the field name to be checked against the column names in the zone data table. + * @return true if field matches one of the zone data table column names, otherwise false. + */ + public boolean isValidZoneTableField(String field){ + return zoneDataTable.getColumnPosition(field) >= 0; + } + + + public String[] getZoneDataTableColumnLabels() { + return zoneDataTable.getColumnLabels(); + } + + public int getNumberOfZones(){ + return NUM_ZONES; + } + + public int getNumberOfSubZones(){ + return NUM_SUBZONES; + } + + public String[] getSubZoneNames() { + return subZoneNames; + } + + public double[] getZonalWalkPercentagesForTaz( int taz ) { + double[] percentages = new double[NUM_SUBZONES]; + for (int i=0; i < NUM_SUBZONES; i++) + percentages[i] = zonalWalkPctArray[i][taz]; + return percentages; + } + + public float getZoneTableValue ( int taz, String fieldName ) { + // get the table row number for the TAZ passed in + int rowIndex = zoneTableRow[taz]; + + // get the table value from the rowIndex and fieldname passed in + return zoneDataTable.getValueAt( rowIndex, fieldName ); + } + + // get the table column from the fieldname passed in + public int[] getZoneTableIntColumn ( String fieldName ) { + return zoneDataTable.getColumnAsInt( fieldName ); + } + + // get the table column from the fieldname passed in + public float[] getZoneTableFloatColumn ( String fieldName ) { + return zoneDataTable.getColumnAsFloat( fieldName ); + } + + /** + * @param tableRowNumber is the zone table row number + * @return zone number for the table row. + */ + public int getTazNumber ( int tableRowNumber ) { + return (int) zoneDataTable.getValueAt( tableRowNumber, tazDataZoneFieldName ); + } + + /** + * @return area type array from the zone data table. + */ + public int[] getZonalAreaType () { + int atFieldPosition = zoneDataTable.getColumnPosition( tazDataAtFieldName ); + if ( atFieldPosition < 0 ) { + logger.error ( String.format("The area type field name = %s defined in %s is not found as a field name in the zone data table.", tazDataAtFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( atFieldPosition ); + } + + /** + * @return district array from the zone data table. + */ + public int[] getZonalDistrict () { + int districtFieldPosition = zoneDataTable.getColumnPosition( tazDataDistFieldName ); + if ( districtFieldPosition < 0 ) { + logger.error ( String.format("The district field name = %s defined in %s is not found as a field name in the zone data table.", tazDataDistFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( districtFieldPosition ); + } + + /** + * @return county array from the zone data table. + */ + public int[] getZonalCounty () { + int countyFieldPosition = zoneDataTable.getColumnPosition( tazDataCountyFieldName ); + if ( countyFieldPosition < 0 ) { + logger.error ( String.format("The county field name = %s defined in %s is not found as a field name in the zone data table.", tazDataCountyFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( countyFieldPosition ); + } + + /** + * @return gradeschool array from the zone data table. + */ + public int[] getZonalGradeSchool () { + int gradeSchoolFieldPosition = zoneDataTable.getColumnPosition( tazDataGradeSchoolFieldName ); + if ( gradeSchoolFieldPosition < 0 ) { + logger.error ( String.format("The gradeSchool field name = %s defined in %s is not found as a field name in the zone data table.", tazDataGradeSchoolFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( gradeSchoolFieldPosition ); + } + + /** + * @return highschool array from the zone data table. + */ + public int[] getZonalHighSchool () { + int highschoolFieldPosition = zoneDataTable.getColumnPosition( tazDataHighSchoolFieldName ); + if ( highschoolFieldPosition < 0 ) { + logger.error ( String.format("The highschool field name = %s defined in %s is not found as a field name in the zone data table.", tazDataHighSchoolFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( highschoolFieldPosition ); + } + + /** + * @return bhhden array from the zone data table. + */ + public float[] getBHHDen () { + int bhhdenFieldPosition = zoneDataTable.getColumnPosition( bhhdenFieldName ); + if ( bhhdenFieldPosition < 0 ) { + logger.error ( String.format("The bhhden field name = %s defined in %s is not found as a field name in the zone data table.", bhhdenFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsFloat( bhhdenFieldPosition ); + } + + /** + * @return bempden array from the zone data table. + */ + public float[] getBEmpDen () { + int bempdenFieldPosition = zoneDataTable.getColumnPosition( bempdenFieldName ); + if ( bempdenFieldPosition < 0 ) { + logger.error ( String.format("The bempden field name = %s defined in %s is not found as a field name in the zone data table.", bempdenFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsFloat( bempdenFieldPosition ); + } + + /** + * @return pef array from the zone data table. + */ + public float[] getPef () { + int pefFieldPosition = zoneDataTable.getColumnPosition( pefFieldName ); + if ( pefFieldPosition < 0 ) { + logger.error ( String.format("The pef field name = %s defined in %s is not found as a field name in the zone data table.", pefFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsFloat( pefFieldPosition ); + } + + /** + * @return ring array from the zone data table. + */ + public int[] getRing () { + int ringFieldPosition = zoneDataTable.getColumnPosition( ringFieldName ); + if ( ringFieldPosition < 0 ) { + logger.error ( String.format("The ring field name = %s defined in %s is not found as a field name in the zone data table.", ringFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( ringFieldPosition ); + } + + + + public int getZoneIsCbd( int taz ) { + return getZoneIsInAreaType( taz, areaTypes[cbdAreaTypesArrayIndex] ); + } + + public int getZoneIsUrban( int taz ) { + return getZoneIsInAreaType( taz, areaTypes[urbanAreaTypesArrayIndex] ); + } + + public int getZoneIsSuburban( int taz ) { + return getZoneIsInAreaType( taz, areaTypes[suburbanAreaTypesArrayIndex] ); + } + + public int getZoneIsRural( int taz ) { + return getZoneIsInAreaType( taz, areaTypes[ruralAreaTypesArrayIndex] ); + } + + private int getZoneIsInAreaType( int taz, int[] areaTypes ) { + int returnValue = 0; + int tazAreaType = (int)getZoneTableValue ( taz, tazDataAtFieldName ); + for ( int atIndex : areaTypes ) { + if ( tazAreaType == atIndex ) { + returnValue = 1; + break; + } + } + return returnValue; + } + + + /** + * @return parkTot field name used in the zone data table. + */ + public String getZonalParkTotFieldName () { + return parkTotFieldName; + } + + + /** + * @return parkRate field name used in the zone data table. + */ + public String getZonalParkRateFieldName () { + return parkRateFieldName; + } + + + /** + * @return parkTot array from the zone data table. + */ + public int[] getZonalParkTot () { + int parkTotFieldPosition = zoneDataTable.getColumnPosition( parkTotFieldName ); + if ( parkTotFieldPosition < 0 ) { + logger.error ( String.format("The parkTot field name = %s defined in %s is not found as a field name in the zone data table.", parkTotFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( parkTotFieldPosition ); + } + + /** + * @return parkLong array from the zone data table. + */ + public int[] getZonalParkLong () { + int parkLongFieldPosition = zoneDataTable.getColumnPosition( parkLongFieldName ); + if ( parkLongFieldPosition < 0 ) { + logger.error ( String.format("The parkLong field name = %s defined in %s is not found as a field name in the zone data table.", parkLongFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsInt( parkLongFieldPosition ); + } + + /** + * @return propFree array from the zone data table. + */ + public float[] getZonalPropFree () { + int propFreeFieldPosition = zoneDataTable.getColumnPosition( propFreeFieldName ); + if ( propFreeFieldPosition < 0 ) { + logger.error ( String.format("The propFree field name = %s defined in %s is not found as a field name in the zone data table.", propFreeFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsFloat( propFreeFieldPosition ); + } + + /** + * @return parkRate array from the zone data table. + */ + public float[] getZonalParkRate () { + int parkRateFieldPosition = zoneDataTable.getColumnPosition( parkRateFieldName ); + if ( parkRateFieldPosition < 0 ) { + logger.error ( String.format("The parkRate field name = %s defined in %s is not found as a field name in the zone data table.", parkRateFieldName, this.getClass().getName() )); + throw new RuntimeException(); + } + return zoneDataTable.getColumnAsFloat( parkRateFieldPosition ); + } + + + + + public float[] getPkAutoRetailAccessibity() { + return pkAutoRetail; + } + + public float[] getPkAutoTotalAccessibity() { + return pkAutoTotal; + } + + public float[] getPkTransitRetailAccessibity() { + return pkTransitRetail; + } + + public float[] getPkTransitTotalAccessibity() { + return pkTransitTotal; + } + + public float[] getOpAutoRetailAccessibity() { + return opAutoRetail; + } + + public float[] getOpAutoTotalAccessibity() { + return opAutoTotal; + } + + public float[] getOpTransitRetailAccessibity() { + return opTransitRetail; + } + + public float[] getOpTransitTotalAccessibity() { + return opTransitTotal; + } + + public float[] getNonMotorizedRetailAccessibity() { + return nonMotorizedRetail; + } + + public float[] getNonMotorizedTotalAccessibity() { + return nonMotorizedTotal; + } + + public float[] getAccess17Accessibity() { + return access17; + } + + public float[] getAccess18Accessibity() { + return access18; + } + + public enum AreaType { + CBD, + URBAN, + SUBURBAN, + RURAL + } + + //not used + public float getOMazDMazDistance(int omaz, int dmaz) { + return((float)-1); + } + + //not used + public float[] getOMazDistances(int omaz) { + return(new float[1]); + } + + //not used + public float[] getAltDistances(int alt) { + return(new float[1]); + } + + //not used + public int getHasTransitAccess(int maz) { + return(-1); + } + + //not used + public int[] getTazsForMazs() { + return (new int[1]); + } + + //not used + public MazTapTazData getMttData() { + MazTapTazData mttData = null; + try { + mttData = new MazTapTazData(null); + } catch (IOException e) { + + } + return(mttData); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/TazDataHandlerRmi.java b/src/java/com/pb/models/ctrampIf/TazDataHandlerRmi.java new file mode 100644 index 0000000..4ae0241 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TazDataHandlerRmi.java @@ -0,0 +1,339 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; + +import com.pb.cmap.tvpb.MazTapTazData; + + +/** + * This class provides methods defined in the TazDataIf interface for accessing zonal data stored in + * its TazDataManager object. + * + * A CT-RAMP tour based model application could create an instance of a subclass of this class, where additional + * project specific varaible definitions and methods are defined and pass that instance to its model + * component objects. + * + * Alternatively, an application could use TazDataHandlerRmi as the base class instead and create a "remoteable" subclass. + * The TazDataHandlerRmi class implements the same interface, so the model component classes can be unaware of whether the + * taz data handler object accesses zonal data from its member object or remotely from a server. Those methods in the + * rmi class access zonal data from a TazDataManager object contained in a "taz data server" object which must exist in + * a separate JVM on the same machine or on another addressable machine over the network. + * + * The flexibility provided by this design is intended to allow the "local" instance to be declared and passed within a single JVM + * to model components for possibly greater performance (yet to be tested and proven) at production run time. + * The "rmi" instance however allows the model components to access zonal data from a "long-running process" (the server + * class may execute for weeks or months). This approach aids in model development as during development, model + * applications can be written to skip startup procedures for reading zonal data, and access them directly from the + * server that is already running. + * + * A similar approach is planned for managing objects such as Household objects and ModelResults objects so that model + * components, for example individual non-mandatory tour related models which occur well into the tour based model stream, + * can be run in a "hot-start" fasion, where the model component of interest is executed immediately where all the + * preliminary data and prior model results it requires are stored in long-running server objects. Testing and debugging + * of these model components can occur without the time required to run through all preliminary steps. + * + * + */ + +public class TazDataHandlerRmi implements TazDataIf, Serializable { + + UtilRmi remote; + String connectString; + + public TazDataHandlerRmi( String hostname, int port, String className ){ + + connectString = String.format("//%s:%d/%s", hostname, port, className ); + remote = new UtilRmi(connectString); + + } + + + + + + public String testRemote() { + Object[] objArray = {}; + return (String)remote.method( "testRemote", objArray); + } + + public int[] getAltToZoneArray () { + Object[] objArray = {}; + return (int[])remote.method( "getAltToZoneArray", objArray); + } + + public int[] getAltToSubZoneArray () { + Object[] objArray = {}; + return (int[])remote.method( "getAltToSubZoneArray", objArray); + } + + public int[] getIndexToZoneArray () { + Object[] objArray = {}; + return (int[])remote.method( "getIndexToZoneArray", objArray); + } + + public int[] getZoneTableRowArray () { + Object[] objArray = {}; + return (int[])remote.method( "getZoneTableRowArray", objArray); + } + + + + /** + * @param field is the field name to be checked against the column names in the zone data table. + * @return true if field matches one of the zone data table column names, otherwise false. + */ + public boolean isValidZoneTableField(String field){ + Object[] objArray = { field }; + return (Boolean)remote.method( "isValidZoneTableField", objArray); + } + + + public String[] getZoneDataTableColumnLabels() { + Object[] objArray = {}; + return (String[])remote.method( "getZoneDataTableColumnLabels", objArray); + } + + public int getNumberOfZones(){ + Object[] objArray = {}; + return (Integer)remote.method( "getNumberOfZones", objArray); + } + + public int getNumberOfSubZones(){ + Object[] objArray = {}; + return (Integer)remote.method( "getNumberOfSubZones", objArray); + } + + public String[] getSubZoneNames() { + Object[] objArray = {}; + return (String[])remote.method( "getSubZoneNames", objArray); + } + + + public double[] getZonalWalkPercentagesForTaz( int taz ) { + Object[] objArray = { taz }; + return (double[])remote.method( "getZonalWalkPercentagesForTaz", objArray); + } + + public float getZoneTableValue ( int taz, String fieldName ) { + Object[] objArray = { taz, fieldName }; + return (Float)remote.method( "getZoneTableValue", objArray); + } + + public int[] getZoneTableIntColumn ( String fieldName ) { + Object[] objArray = { fieldName }; + return (int[])remote.method( "getZoneTableIntColumn", objArray); + } + + // get the table column from the fieldname passed in + public float[] getZoneTableFloatColumn ( String fieldName ) { + Object[] objArray = { fieldName }; + return (float[])remote.method( "getZoneTableFloatColumn", objArray); + } + + + + /** + * @param tableRowNumber is the zone table row number + * @return zone number for the table row. + */ + public int getTazNumber ( int tableRowNumber ) { + Object[] objArray = { tableRowNumber }; + return (Integer)remote.method( "getTazNumber", objArray); + } + + /** + * @return area type from the zone data table for the zone. + */ + public int[] getZonalAreaType () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalAreaType", objArray); + } + + /** + * @return district from the zone data table for the zone. + */ + public int[] getZonalDistrict () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalDistrict", objArray); + } + + public int[] getZonalParkTot () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalParkTot", objArray); + } + + public int[] getZonalParkLong () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalParkLong", objArray); + } + + public float[] getZonalPropFree () { + Object[] objArray = {}; + return (float[])remote.method( "getZonalPropFree", objArray); + } + + public float[] getZonalParkRate () { + Object[] objArray = {}; + return (float[])remote.method( "getZonalParkRate", objArray); + } + + public String getZonalParkTotFieldName () { + Object[] objArray = {}; + return (String)remote.method( "getZonalParkTotFieldName", objArray); + } + + public String getZonalParkRateFieldName () { + Object[] objArray = {}; + return (String)remote.method( "getZonalParkRateFieldName", objArray); + } + + /** + * @return integer county value from the zone data table for the zone. + */ + public int[] getZonalCounty () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalCounty", objArray); + } + + public int[] getZonalGradeSchool () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalGradeSchool", objArray); + } + + public int[] getZonalHighSchool () { + Object[] objArray = {}; + return (int[])remote.method( "getZonalHighSchool", objArray); + } + + public int getZoneIsCbd( int taz ) { + Object[] objArray = { taz }; + return (Integer)remote.method( "getZoneIsCbd", objArray); + } + + public float[] getBHHDen() { + Object[] objArray = {}; + return (float[])remote.method( "getBHHDen", objArray); + } + + public float[] getBEmpDen() { + Object[] objArray = {}; + return (float[])remote.method( "getBEmpDen", objArray); + } + + public float[] getPef() { + Object[] objArray = {}; + return (float[])remote.method( "getPef", objArray); + } + + public int[] getRing() { + Object[] objArray = {}; + return (int[])remote.method( "getRing", objArray); + } + + public int getZoneIsUrban( int taz ) { + Object[] objArray = { taz }; + return (Integer)remote.method( "getZoneIsUrban", objArray); + } + + public int getZoneIsSuburban( int taz ) { + Object[] objArray = { taz }; + return (Integer)remote.method( "getZoneIsSuburban", objArray); + } + + public int getZoneIsRural( int taz ) { + Object[] objArray = { taz }; + return (Integer)remote.method( "getZoneIsRural", objArray); + } + + + public float[] getPkAutoRetailAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getPkAutoRetailAccessibity", objArray); + } + + public float[] getPkAutoTotalAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getPkAutoTotalAccessibity", objArray); + } + + public float[] getPkTransitRetailAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getPkTransitRetailAccessibity", objArray); + } + + public float[] getPkTransitTotalAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getPkTransitTotalAccessibity", objArray); + } + + public float[] getOpAutoRetailAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getOpAutoRetailAccessibity", objArray); + } + + public float[] getOpAutoTotalAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getOpAutoTotalAccessibity", objArray); + } + + public float[] getOpTransitRetailAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getOpTransitRetailAccessibity", objArray); + } + + public float[] getOpTransitTotalAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getOpTransitTotalAccessibity", objArray); + } + + public float[] getNonMotorizedRetailAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getNonMotorizedRetailAccessibity", objArray); + } + + public float[] getNonMotorizedTotalAccessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getNonMotorizedTotalAccessibity", objArray); + } + + public float[] getAccess17Accessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getAccess17Accessibity", objArray); + } + + public float[] getAccess18Accessibity() { + Object[] objArray = {}; + return (float[])remote.method( "getAccess18Accessibity", objArray); + } + + public float getOMazDMazDistance(int omaz, int dmaz) { + Object[] objArray = { omaz, dmaz }; + return (Float)remote.method( "getOMazDMazDistance", objArray); + } + + public float[] getOMazDistances(int omaz) { + Object[] objArray = { omaz }; + return (float[])remote.method( "getOMazDistances", objArray); + } + + public float[] getAltDistances(int alt) { + Object[] objArray = { alt }; + return (float[])remote.method( "getAltDistances", objArray); + } + + public int getHasTransitAccess(int maz) { + Object[] objArray = { maz }; + return (Integer)remote.method( "getHasTransitAccess", objArray); + } + + public int[] getTazsForMazs() { + Object[] objArray = {}; + return (int[])remote.method( "getTazsForMazs", objArray); + } + + public MazTapTazData getMttData() { + Object[] objArray = {}; + return (MazTapTazData)remote.method( "getMttData", objArray); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/TazDataIf.java b/src/java/com/pb/models/ctrampIf/TazDataIf.java new file mode 100644 index 0000000..852b3b3 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TazDataIf.java @@ -0,0 +1,168 @@ +package com.pb.models.ctrampIf; + +import com.pb.cmap.tvpb.MazTapTazData; + +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 1, 2008 + * Time: 9:58:21 AM + * + * Interface for accessing zonal information used by CT-RAMP modules + */ +public interface TazDataIf { + + public String testRemote(); + public int[] getAltToZoneArray (); + public int[] getAltToSubZoneArray (); + public int[] getIndexToZoneArray (); + public int[] getZoneTableRowArray (); + + public int getZoneIsCbd( int taz ); + public int getZoneIsUrban( int taz ); + public int getZoneIsSuburban( int taz ); + public int getZoneIsRural( int taz ); + + public float[] getPkAutoRetailAccessibity(); + public float[] getPkAutoTotalAccessibity(); + public float[] getPkTransitRetailAccessibity(); + public float[] getPkTransitTotalAccessibity(); + public float[] getOpAutoRetailAccessibity(); + public float[] getOpAutoTotalAccessibity(); + public float[] getOpTransitRetailAccessibity(); + public float[] getOpTransitTotalAccessibity(); + public float[] getNonMotorizedRetailAccessibity(); + public float[] getNonMotorizedTotalAccessibity(); + public float[] getAccess17Accessibity(); + public float[] getAccess18Accessibity(); + + //maz, tap extensions + public float getOMazDMazDistance(int omaz, int dmaz); + public float[] getOMazDistances(int omaz); + public float[] getAltDistances(int alt); + public int[] getTazsForMazs(); + public MazTapTazData getMttData(); + public int getHasTransitAccess(int maz); + /** + * + * @param field is the field name to be checked against the column names in the zone data table. + * @return true if field matches one of the zone data table column names, otherwise false. + */ + public boolean isValidZoneTableField(String field); + + /** + * @return a String[] of the column labels in the zone data table + */ + public String[] getZoneDataTableColumnLabels(); + + /** + * @return an int value for the number of zones, i.e. rows in the zone data table + */ + public int getNumberOfZones(); + + /** + * @return an int value for the number of subZones, i.e. number of walkTransit accessible segments defined + * in model for zones. Typical value might be 3, "no walk access", "short walk access", "long walk access". + */ + public int getNumberOfSubZones(); + + /** + * @return a String[] for the subZone names, e.g. "no walk access", "short walk access", "long walk access". + */ + public String[] getSubZoneNames(); + + /** + * @param taz is the taz index for the zonalWalkPctArray which is dimensioned to ZONES+1, assuming taz index values + * range from 1 to NUM_ZONES. + * @return a double[], dimensioned to NUM_SIBZONES, with the subzone proportions for the TAZ passed in + */ + public double[] getZonalWalkPercentagesForTaz( int taz ); + + /** + * @param taz is the taz index for the zone data table which is dimensioned to ZONES+1, assuming taz index values + * range from 1 to NUM_ZONES. + * @param fieldName is the column label in the zone data table. + * @return a float value from the zone data table at the specified row index and column label. + */ + public float getZoneTableValue ( int taz, String fieldName ); + + public int[] getZoneTableIntColumn ( String fieldName ); + + public float[] getZoneTableFloatColumn ( String fieldName ); + + /** + * @param tableRowNumber is the zone table row number + * @return zone number for the table row. + */ + public int getTazNumber ( int tableRowNumber ); + + /** + * @return area type from the zone data table for the zone index. + */ + public int[] getZonalAreaType (); + + /** + * @return district from the zone data table for the zone index. + */ + public int[] getZonalDistrict (); + + /** + * @return integer county value from the zone data table for the zone index. + */ + public int[] getZonalCounty (); + + /** + * @return integer grade school value from the zone data table for the zone index. + */ + public int[] getZonalGradeSchool (); + + /** + * @return integer high school value from the zone data table for the zone index. + */ + public int[] getZonalHighSchool (); + + /** + * @return the parking rate array + */ + float[] getZonalParkRate (); + + /** + * @return the proportion of free parking array + */ + float[] getZonalPropFree (); + + /** + * @return the number of long parking spots array + */ + int[] getZonalParkLong (); + + /** + * @return the number of parking spots array + */ + int[] getZonalParkTot (); + + public String getZonalParkTotFieldName (); + public String getZonalParkRateFieldName (); + + + /** + * @return bhhden array from the zone data table. + */ + public float[] getBHHDen (); + + /** + * @return bempden array from the zone data table. + */ + public float[] getBEmpDen (); + + /** + * @return pef array from the zone data table. + */ + public float[] getPef (); + + /** + * @return ring array from the zone data table. + */ + public int[] getRing (); + +} diff --git a/src/java/com/pb/models/ctrampIf/TimeDMU.java b/src/java/com/pb/models/ctrampIf/TimeDMU.java new file mode 100644 index 0000000..d7c2488 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TimeDMU.java @@ -0,0 +1,102 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + + +public class TimeDMU implements Serializable, VariableTable { + + IndexValues dmuIndex = null; + + // switches used in the Individual Mandatory Tour Frequency Model + int imtfWorkSwitch, imtfSchoolSwitch; + + public TimeDMU () { + dmuIndex = new IndexValues(); + } + + + public void setDmuIndexValues( int hhId, int zoneId, int origTaz, int destTaz, boolean debugUec ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( zoneId ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( debugUec ) { + dmuIndex.setDebug(true); +// dmuIndex.setDebugLabel ( "Debug IMTF Time UEC" ); + dmuIndex.setDebugLabel ( "Debug AO Time UEC" ); + } + + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + + +// /** +// * Used in the Individual Mandatory Tour Frequency model; set to true +// * when the model is applied for a worker (to get round trip time to work, +// * which uses peak skims) +// * @param workOn +// */ +// public void setImtfWorkSwitch(int workOn){ +// imtfWorkSwitch = workOn; +// } +// +// /** +// * Used in the Individual Mandatory Tour Frequency model; set to true +// * when the model is applied for a student (to get round trip time to school, +// * which uses peak skims in the o/d direction and off-peak skims in the d/o +// * direction) +// * @param schoolOn +// */ +// public void setImtfSchoolSwitch(int schoolOn){ +// imtfSchoolSwitch = schoolOn; +// } +// +// public int getImtfWorkSwitch(){ +// return this.imtfWorkSwitch; +// } +// +// public int getImtfSchoolSwitch(){ +// return this.imtfSchoolSwitch; +// } + + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public int getIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} + + diff --git a/src/java/com/pb/models/ctrampIf/TourDepartureTimeAndDurationDMU.java b/src/java/com/pb/models/ctrampIf/TourDepartureTimeAndDurationDMU.java new file mode 100644 index 0000000..a5f1150 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TourDepartureTimeAndDurationDMU.java @@ -0,0 +1,826 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.jppf.HouseholdIndividualMandatoryTourFrequencyModel; + + +public class TourDepartureTimeAndDurationDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(TourDepartureTimeAndDurationDMU.class); + + private static int JOINT_TOUR_COMPOSITION_CHILDREN_ONLY = 2; + + protected HashMap methodIndexMap; + + + protected IndexValues dmuIndex; + + protected PersonIf person; + protected HouseholdIf household; + protected TourIf tour; + + protected double[] modeChoiceLogsums; + + private int[] altStarts; + private int[] altEnds; + + protected int originAreaType, destinationAreaType; + + protected int tourNumber; + + protected int firstTour; + protected int subsequentTour; + protected int endOfPreviousScheduledTour; + protected int subsequentTourIsWork; + protected int subsequentTourIsSchool; + + + protected ModelStructure modelStructure; + + public TourDepartureTimeAndDurationDMU( ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + } + + public void setPerson(PersonIf passedInPerson){ + person = passedInPerson; + } + + public void setHousehold(HouseholdIf passedInHousehold){ + household = passedInHousehold; + + // set the origin and zone indices + dmuIndex.setZoneIndex(household.getHhTaz()); + dmuIndex.setHHIndex(household.getHhId()); + + // set the debug flag that can be used in the UEC + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( household.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug DepartTime UEC" ); + } + + } + + public void setTour(TourIf passedInTour){ + tour = passedInTour; + } + + public void setOriginZone(int zone){ + dmuIndex.setOriginZone(zone); + } + + public void setDestinationZone(int zone){ + dmuIndex.setDestZone(zone); + } + + public void setOriginAreaType(int areaType){ + originAreaType = areaType; + } + + public void setDestinationAreaType(int areaType){ + destinationAreaType = areaType; + } + + public void setFirstTour(int trueOrFalse) + { + firstTour = trueOrFalse; + } + + public void setSubsequentTour(int trueOrFalse) + { + subsequentTour = trueOrFalse; + } + + public void setSubsequentTourIsWork(int trueOrFalse) + { + subsequentTourIsWork = trueOrFalse; + } + + public void setSubsequentTourIsSchool(int trueOrFalse) + { + subsequentTourIsSchool = trueOrFalse; + } + + /** + * Set the sequence number of this tour among all scheduled + * @param tourNum + */ + public void setTourNumber( int tourNum ){ + tourNumber = tourNum; + } + + public void setEndOfPreviousScheduledTour ( int endHr ){ + endOfPreviousScheduledTour = endHr; + } + + public void setModeChoiceLogsums( double[] logsums ) { + modeChoiceLogsums = logsums; + } + + public void setTodAlts( int[] altStarts, int[] altEnds ){ + this.altStarts = altStarts; + this.altEnds = altEnds; + } + + public IndexValues getIndexValues(){ + return(dmuIndex); + } + + public HouseholdIf getDmuHouseholdObject() { + return household; + } + + public int getOriginZone(){ + return(dmuIndex.getOriginZone()); + } + + public int getDestinationZone(){ + return(dmuIndex.getDestZone()); + } + + public int getOriginAreaType(){ + return(originAreaType); + } + + public int getDestinationAreaType(){ + return(destinationAreaType); + } + + public int getPersonIsAdult() { + return person.getPersonIsAdult(); + } + + public int getPreDrivingAgeChild() + { + return (person.getPersonIsStudentNonDriving() == 1 || person.getPersonIsPreschoolChild() == 1 ) ? 1 : 0; + } + + public int getPersonType() + { + return person.getPersonTypeNumber(); + } + + // return 1 if the person is preschool + public int getPreschool() + { + return person.getPersonIsPreschoolChild() == 1 ? 1 : 0; + + } + + public int getPersonAge() + { + return person.getAge(); + } + + public int getPersonIsFemale() + { + return person.getGender() == 2 ? 1 : 0; + } + + public int getHouseholdSize() + { + return household.getHhSize(); + } + + public int getNumPreschoolChildrenInHh() + { + return household.getNumPreschool(); + } + + public int getNumNonWorkingAdultsInHh() + { + return household.getNumberOfNonWorkingAdults(); + } + + public int getNumChildrenUnder16InHh() + { + return household.getNumChildrenUnder16(); + } + + public int getNumIndivShopTours() + { + int count = 0; + for ( TourIf t : person.getListOfIndividualNonMandatoryTours() ) + if (t.getTourPrimaryPurpose().equalsIgnoreCase(ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME)) count++; + + return count; + } + + public int getNumIndivMaintTours() + { + int count = 0; + for ( TourIf t : person.getListOfIndividualNonMandatoryTours() ) + if (t.getTourPrimaryPurpose().equalsIgnoreCase(ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME)) count++; + + return count; + } + + public int getNumIndivVisitTours() + { + int count = 0; + for ( TourIf t : person.getListOfIndividualNonMandatoryTours() ) + if (t.getTourPrimaryPurpose().equalsIgnoreCase(ModelStructure.VISITING_PRIMARY_PURPOSE_NAME)) count++; + + return count; + } + + public int getNumIndivDiscrTours() + { + int count = 0; + for ( TourIf t : person.getListOfIndividualNonMandatoryTours() ) + if (t.getTourPrimaryPurpose().equalsIgnoreCase(ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME)) count++; + + return count; + } + + // for joint tours - if an adult is in the party, return 1. + public int getAdultInTour() { + return tour.getJointTourComposition() != JOINT_TOUR_COMPOSITION_CHILDREN_ONLY ? 1 : 0; + } + + public int getNumChildrenInHh() { + return household.getNumChildrenUnder19(); + } + + public int getFullTimeWorker(){ + return(this.person.getPersonTypeIsFullTimeWorker()); + } + + public int getPartTimeWorker(){ + return(this.person.getPersonTypeIsPartTimeWorker()); + } + + public int getUniversityStudent(){ + return(this.person.getPersonIsUniversityStudent()); + } + + public int getStudentDrivingAge() { + return(this.person.getPersonIsStudentDriving()); + } + + public int getStudentNonDrivingAge() { + return(this.person.getPersonIsStudentNonDriving()); + } + + public int getNonWorker(){ + return(this.person.getPersonIsNonWorkingAdultUnder65()); + } + + public int getRetired(){ + return(this.person.getPersonIsNonWorkingAdultOver65()); + } + + public int getAllAdultsFullTimeWorkers() { + PersonIf[] p = household.getPersons(); + boolean allAdultsAreFullTimeWorkers = true; + for (int i=1; i < p.length; i++) { + if ( p[i].getPersonIsAdult() == 1 && p[i].getPersonIsFullTimeWorker() == 0 ) { + allAdultsAreFullTimeWorkers = false; + break; + } + } + + if ( allAdultsAreFullTimeWorkers ) + return 1; + else + return 0; + } + + public int getSubtourPurposeIsEatOut() + { + if (tour.getSubTourPurpose().equalsIgnoreCase(ModelStructure.AT_WORK_EAT_PURPOSE_NAME)) return 1; + else return 0; + } + + public int getSubtourPurposeIsBusiness() + { + if (tour.getSubTourPurpose().equalsIgnoreCase(ModelStructure.AT_WORK_BUSINESS_PURPOSE_NAME)) return 1; + else return 0; + } + + public int getSubtourPurposeIsOther() + { + if (tour.getSubTourPurpose().equalsIgnoreCase(ModelStructure.AT_WORK_MAINT_PURPOSE_NAME)) return 1; + else return 0; + } + + public int getTourPrimaryPurposeIsShopping() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeIsEatOut() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeIsMaint() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeIsVisit() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.VISITING_PRIMARY_PURPOSE_NAME ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeIsDiscr() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME ) ) + return 1; + else + return 0; + } + + public int getSubtourPurposeIndex() { + if ( tour.getTourCategoryIsAtWork() ) { + return tour.getTourPrimaryPurposeIndex(); + } + else { + return 0; + } + } + + public int getAdultsInTour() { + + int count = 0; + if ( tour.getTourCategoryIsJointNonMandatory() ) { + PersonIf[] persons = household.getPersons(); + + byte[] personNums = tour.getPersonNumArray(); + for (int i=0; i < personNums.length; i++) { + int p = personNums[i]; + if ( persons[p].getPersonIsAdult() == 1 ) + count++; + } + } + else if ( tour.getTourCategoryIsIndivNonMandatory() ) { + if ( person.getPersonIsAdult() == 1 ) + count = 1; + } + + return count; + } + + public int getChildrenInTour() { + + int count = 0; + if ( tour.getTourCategoryIsJointNonMandatory() ) { + PersonIf[] persons = household.getPersons(); + + byte[] personNums = tour.getPersonNumArray(); + for (int i=0; i < personNums.length; i++) { + int p = personNums[i]; + if ( persons[p].getPersonIsAdult() == 0 ) + count++; + } + } + else if ( tour.getTourCategoryIsIndivNonMandatory() ) { + if ( person.getPersonIsAdult() == 0 ) + count = 1; + } + + return count; + + } + + // return 1 if at least one preschool or pre-driving child is in joint tour, otherwise 0. + public int getPreschoolPredrivingInTour() { + + int count = 0; + if ( tour.getTourCategoryIsJointNonMandatory() ) { + PersonIf[] persons = household.getPersons(); + byte[] personNums = tour.getPersonNumArray(); + for (int i=0; i < personNums.length; i++) { + int p = personNums[i]; + if ( persons[p].getPersonIsPreschoolChild() == 1 || persons[p].getPersonIsStudentNonDriving() == 1 ) + return 1; + } + } + else if ( tour.getTourCategoryIsIndivNonMandatory() ) { + if ( person.getPersonIsPreschoolChild() == 1 || person.getPersonIsStudentNonDriving() == 1 ) + count = 1; + } + + return count; + + } + + // return 1 if at least one university student is in joint tour, otherwise 0. + public int getUnivInTour() { + + int count = 0; + if ( tour.getTourCategoryIsJointNonMandatory() ) { + PersonIf[] persons = household.getPersons(); + byte[] personNums = tour.getPersonNumArray(); + for (int i=0; i < personNums.length; i++) { + int p = personNums[i]; + if ( persons[p].getPersonIsUniversityStudent() == 1 ) + return 1; + } + } + else if ( tour.getTourCategoryIsIndivNonMandatory() ) { + if ( person.getPersonIsUniversityStudent() == 1 ) + count = 1; + } + + return count; + + } + + // return 1 if all adults in joint tour are fulltime workers, 0 otherwise; + public int getAllWorkFull() { + + if ( tour.getTourCategoryIsJointNonMandatory() ) { + int adultCount = 0; + int ftWorkerAdultCount = 0; + + PersonIf[] persons = household.getPersons(); + byte[] personNums = tour.getPersonNumArray(); + for (int i=0; i < personNums.length; i++) { + int p = personNums[i]; + if ( persons[p].getPersonIsAdult() == 1 ) { + adultCount++; + if ( persons[p].getPersonIsFullTimeWorker() == 1 ) + ftWorkerAdultCount++; + } + } + + if ( adultCount > 0 && adultCount == ftWorkerAdultCount ) + return 1; + else + return 0; + } + + return 0; + + } + + public int getPartyComp() { + if ( tour.getTourCategoryIsJointNonMandatory() ) { + return tour.getJointTourComposition(); + } + else { + return 0; + } + } + + /** + * @return number of individual non-mandatory tours, excluding escort, for the + * person + */ + public int getPersonNonMandatoryTotalNoEscort() + { + int count = 0; + for (TourIf t : person.getListOfIndividualNonMandatoryTours()) + if (!t.getTourPrimaryPurpose().startsWith("escort")) count++; + return count; + } + + /** + * @return number of individual non-mandatory discretionary tours for the person + */ + public int getPersonDiscrToursTotal() + { + int count = 0; + for (TourIf t : person.getListOfIndividualNonMandatoryTours()) + { + if (t.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME) || + t.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.VISITING_PRIMARY_PURPOSE_NAME) || + t.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME) ) + count++; + } + return count; + } + + /** + * @return number of individual non-mandatory tours, excluding escort, for the person + */ + public int getPersonEscortTotal() + { + int count = 0; + for (TourIf t : person.getListOfIndividualNonMandatoryTours()) + if (t.getTourPrimaryPurpose().startsWith("escort")) count++; + return count; + } + + public int getJointTourPartySize() + { + int count = 0; + if (tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) + count = tour.getPersonNumArray().length; + + return count; + } + + public int getKidsOnJointTour() + { + + int count = 0; + if (tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) + { + PersonIf[] persons = household.getPersons(); + + byte[] personNums = tour.getPersonNumArray(); + for (int i = 0; i < personNums.length; i++) + { + int p = personNums[i]; + if ((persons[p].getPersonIsPreschoolChild() + persons[p].getPersonIsStudentNonDriving() + persons[p].getPersonIsStudentDriving()) > 0 ) count++; + } + } + + return count > 0 ? 1 : 0; + + } + + public int getHhJointTotal() + { + TourIf[] jt = household.getJointTourArray(); + if (jt == null) return 0; + else return jt.length; + } + + public int getPersonMandatoryTotal() + { + return person.getListOfWorkTours().size() + person.getListOfSchoolTours().size(); + } + + public int getPersonJointTotal() + { + TourIf[] jtArray = household.getJointTourArray(); + if (jtArray == null) + { + return 0; + } else + { + int numJtParticipations = 0; + for (TourIf jt : jtArray) + { + byte[] personJtIndices = jt.getPersonNumArray(); + for (int pNum : personJtIndices) + { + if (pNum == person.getPersonNum()) + { + numJtParticipations++; + break; + } + } + } + return numJtParticipations; + } + } + + public int getPersonJointAndIndivDiscrToursTotal() + { + + int totDiscr = getPersonDiscrToursTotal(); + + TourIf[] jtArray = household.getJointTourArray(); + if (jtArray == null) + { + return totDiscr; + } else + { + // count number of joint discretionary tours person participates in + int numJtParticipations = 0; + for (TourIf jt : jtArray) + { + if (jt.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME) || + jt.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.VISITING_PRIMARY_PURPOSE_NAME) || + jt.getTourPrimaryPurpose().equalsIgnoreCase( ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME) ) + { + byte[] personJtIndices = jt.getPersonNumArray(); + for (int pNum : personJtIndices) + { + if (pNum == person.getPersonNum()) + { + numJtParticipations++; + break; + } + } + } + } + return numJtParticipations + totDiscr; + } + } + + public int getFirstTour(){ + return firstTour; + } + + public int getSubsequentTour(){ + return subsequentTour; + } + + public int getNumberOfOutboundStops(){ + return(tour.getNumOutboundStops()); + } + + public int getNumberOfInboundStops(){ + return(tour.getNumInboundStops()); + } + + public int getWorkAndSchoolToursByWorker(){ + int returnValue = 0; + if( person.getPersonIsWorker() == 1 ){ + if ( person.getImtfChoice() == HouseholdIndividualMandatoryTourFrequencyModel.CHOICE_WORK_AND_SCHOOL ) + returnValue = 1; + } + return returnValue; + } + + public int getWorkAndSchoolToursByStudent(){ + int returnValue = 0; + if( person.getPersonIsStudent() == 1 ){ + if ( person.getImtfChoice() == HouseholdIndividualMandatoryTourFrequencyModel.CHOICE_WORK_AND_SCHOOL ) + returnValue = 1; + } + return returnValue; + } + + public double getModeChoiceLogsumAlt (int alt) { + + int startPeriod = altStarts[alt-1]; + int endPeriod = altEnds[alt-1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + + return modeChoiceLogsums[index]; + + } + + /** + * get the number of tours left to be scheduled, including the current tour + * @return number of tours left to be scheduled, including the current tour + */ + public int getToursLeftToSchedule() + { + if ( tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY) ){ + TourIf[] jt = household.getJointTourArray(); + return jt.length - tourNumber + 1; + } + else + return person.getListOfIndividualNonMandatoryTours().size() - tourNumber + 1; + } + + + + public int getPrevTourEndsThisDeparturePeriodAlt (int alt) { + + // get the departure period for the current alternative + int thisTourStartsPeriod = altStarts[alt-1]; + + if ( person.isPreviousArrival( thisTourStartsPeriod ) ) + return 1; + else + return 0; + + } + + + public int getPrevTourBeginsThisArrivalPeriodAlt (int alt) { + + // get the arrival period for the current alternative + int thisTourEndsPeriod = altStarts[alt-1]; + + if ( person.isPreviousDeparture( thisTourEndsPeriod ) ) + return 1; + else + return 0; + + } + + + public int getAdjWindowBeforeThisPeriodAlt(int alt){ + + int thisTourStartsPeriod = altStarts[alt-1]; + + int numAdjacentPeriodsAvailable = 0; + for (int i=thisTourStartsPeriod-1; i >= 0; i--) { + if ( person.isPeriodAvailable(i) ) + numAdjacentPeriodsAvailable++; + else + break; + } + + return numAdjacentPeriodsAvailable; + + } + + public int getAdjWindowAfterThisPeriodAlt(int alt){ + + int thisTourEndsPeriod = altEnds[alt-1]; + + int numAdjacentPeriodsAvailable = 0; + for (int i=thisTourEndsPeriod+1; i < modelStructure.getNumberOfTimePeriods(); i++) { + if ( person.isPeriodAvailable(i) ) + numAdjacentPeriodsAvailable++; + else + break; + } + + return numAdjacentPeriodsAvailable; + + } + + + public int getRemainingPeriodsAvailableAlt( int alt ){ + + int periodsAvail = person.getAvailableWindow(); + + int start = altStarts[alt-1]; + int end = altEnds[alt-1]; + + // determine the availabilty of each period after the alternative time window is hypothetically scheduled + // if start == end, the availability won't change, so no need to compute. + if ( start != end ) { + + // the start and end periods will always be available after scheduling, so don't need to check them. + // the periods between start/end must be 0 or the alternative could not have been available, + // so count them all as unavailable after scheduling this window. + periodsAvail -= ( end - start - 1 ); + + } + + return periodsAvail; + + } + + + public float getRemainingInmToursToAvailablePeriodsRatioAlt( int alt ){ + int periodsAvail = getRemainingPeriodsAvailableAlt( alt ); + if ( periodsAvail > 0 ) { + float ratio = (float)( person.getListOfIndividualNonMandatoryTours().size() - tourNumber ) / periodsAvail; + return ratio; + } + else + return -999; + } + + + public int getMaximumAvailableTimeWindow() + { + return person.getMaximumContinuousAvailableWindow(); + } + + public int getMaxJointTimeWindow( TourIf t) + { + return household.getMaxJointTimeWindow(t); + } + + public int getEndOfPreviousTour() { + return endOfPreviousScheduledTour; + } + + + public int getTourCategoryIsJoint() { + return tour.getTourCategoryIsJointNonMandatory() ? 1 : 0; + } + + + + + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/TourIf.java b/src/java/com/pb/models/ctrampIf/TourIf.java new file mode 100644 index 0000000..5f9ec54 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TourIf.java @@ -0,0 +1,158 @@ +package com.pb.models.ctrampIf; + +import org.apache.log4j.Logger; + +public interface TourIf +{ + + public abstract PersonIf getPersonObject(); + + public abstract void setPersonObject(PersonIf p); + + public abstract void setPersonNumArray(byte[] personNums); + + public abstract byte[] getPersonNumArray(); + + public abstract boolean getPersonInJointTour(PersonIf person); + + public abstract void setJointTourComposition(int compositionAlternative); + + public abstract int getJointTourComposition(); + + public abstract void setTourPurpose(String name); + + public abstract String getTourPurpose(); + + public abstract String getTourCategory(); + + public abstract byte getTourCategoryIndex(); + + public abstract String getTourPrimaryPurpose(); + + public abstract int getTourPrimaryPurposeIndex(); + + public abstract boolean getTourCategoryIsMandatory(); + + public abstract boolean getTourCategoryIsAtWork(); + + public abstract boolean getTourCategoryIsJointNonMandatory(); + + public abstract boolean getTourCategoryIsIndivNonMandatory(); + + public abstract int getTourModeChoice(); + + public String getSubTourPurpose(); + + public void setSubTourPurpose(String name); + + + //TODO: probably need to add a setter method so the project specific code can + // set the mode alternatives that are SOV, rather than have them hard-coded as they are. + public abstract void setTourId(int id); + + public abstract void setTourOrigTaz(int origTaz); + + public abstract void setTourDestTaz(int destTaz); + + public abstract void setTourBTapIn(int tap); + + public abstract void setTourATapIn(int tap); + + public abstract void setTourBTapOut(int tap); + + public abstract void setTourATapOut(int tap); + + public abstract void setTourOrigWalkSubzone(int subzone); + + public abstract void setTourDestWalkSubzone(int subzone); + + public abstract void setTourDepartPeriod( int departInterval); + + public abstract void setTourArrivePeriod( int arriveInterval); + + public abstract void setTourModeChoice(int modeIndex); + + public abstract void setTourParkTaz(int parkTaz); + + public abstract int getTourOrigTaz(); + + public abstract int getTourDestTaz(); + + public abstract int getTourBTapIn(); + + public abstract int getTourATapIn(); + + public abstract int getTourBTapOut(); + + public abstract int getTourATapOut(); + + public abstract int getTourOrigWalkSubzone(); + + public abstract int getTourDestWalkSubzone(); + + public abstract int getTourDepartPeriod(); + + public abstract int getTourArrivePeriod(); + + public abstract int getTourParkTaz(); + + public abstract int getHhId(); + + public abstract int getHhTaz(); + + public abstract int getTourId(); + + public int getWorkTourIndexFromSubtourId( int subtourId ); + + public int getSubtourIdFromIndices(int workTourIndex, int subtourIndex ); + + public abstract void setSubtourFreqChoice(int choice); + + public abstract int getSubtourFreqChoice(); + + public abstract void setStopFreqChoice(int chosenAlt); + + public abstract int getStopFreqChoice(); + + public abstract void createOutboundStops( String[] stopOrigPurposes, String[] stopDestPurposes, int[] stopPurposeIndex ); + + public abstract void createInboundStops( String[] stopOrigPurposes, String[] stopDestPurposes, int[] stopPurposeIndex ); + + /** + * Create a Stop object to represent a half-tour where no stops were generated. The id for the stop is set + * to -1 so that trips for half-tours without stops can be distinguished in the output trip files from + * turs that have stops. Trips for these tours come from stop objects with ids in the range 0,...,3. + * + * @param origPurp is "home" or "work" (for at-work subtours) if outbound, or the primary tour purpose if inbound + * @param destPurp is "home" or "work" (for at-work subtours) if inbound, or the primary tour purpose if outbound + * @param inbound is true if the half-tour is inbound, or false if outbound. + * @return the created Stop object. + */ + public abstract StopIf createStop(ModelStructure modelStructure, String origPurp, + String destPurp, boolean inbound, boolean subtour); + + public abstract int getNumOutboundStops(); + + public abstract int getNumInboundStops(); + + public abstract StopIf[] getOutboundStops(); + + public abstract StopIf[] getInboundStops(); + + public abstract void clearStopModelResults(); + + public abstract String getTourWindow(String purposeAbbreviation); + + public abstract void logTourObject(Logger logger, int totalChars); + + public abstract void logEntireTourObject(Logger logger); + + public abstract void setTourModalUtilities(float[] utils); + + public abstract float[] getTourModalUtilities(); + + public abstract void setTourModalProbabilities(float[] probs); + + public abstract float[] getTourModalProbabilities(); + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/TourModeChoiceDMU.java b/src/java/com/pb/models/ctrampIf/TourModeChoiceDMU.java new file mode 100644 index 0000000..e292e0c --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TourModeChoiceDMU.java @@ -0,0 +1,579 @@ +package com.pb.models.ctrampIf; + +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +public class TourModeChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(TourModeChoiceDMU.class); + + protected HashMap methodIndexMap; + + protected TourIf tour; + protected TourIf workTour; + protected PersonIf person; + protected HouseholdIf hh; + protected IndexValues dmuIndex; + + private ModelStructure modelStructure; + + float genCostWT_In; + float genCostDL_In; + float genCostDP_In; + int OtapWT_In; + int DtapWT_In; + int OtapDL_In; + int DtapDL_In; + int OtapDP_In; + int DtapDP_In; + + float genCostWT_Out; + float genCostDL_Out; + float genCostDP_Out; + int OtapWT_Out; + int DtapWT_Out; + int OtapDL_Out; + int DtapDL_Out; + int OtapDP_Out; + int DtapDP_Out; + + public TourModeChoiceDMU( ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + } + + + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public void setPersonObject ( PersonIf personObject ) { + person = personObject; + } + + public PersonIf getPersonObject () { + return person; + } + + public void setTourObject ( TourIf tourObject ) { + tour = tourObject; + } + + public void setWorkTourObject ( TourIf tourObject ) { + workTour = tourObject; + } + + public TourIf getTourObject () { + return tour; + } + + public TourIf getWorkTourObject () { + return workTour; + } + + public float getGenCostWT_In() { + return genCostWT_In; + } + + public float getGenCostDL_In() { + return genCostDL_In; + } + + public float getGenCostDP_In() { + return genCostDP_In; + } + + public int getOtapWT_In() { + return OtapWT_In; + } + + public int getDtapWT_In() { + return DtapWT_In; + } + + public int getOtapDL_In() { + return OtapDL_In; + } + + public int getDtapDL_In() { + return DtapDL_In; + } + + public int getOtapDP_In() { + return OtapDP_In; + } + + public int getDtapDP_In() { + return DtapDP_In; + } + + public void setGenCostWT_In(float genCost) { + this.genCostWT_In = genCost; + } + + public void setGenCostDL_In(float genCost) { + this.genCostDL_In = genCost; + } + + public void setGenCostDP_In(float genCost) { + this.genCostDP_In = genCost; + } + + public void setOtapWT_In(int Otap) { + this.OtapWT_In = Otap; + } + + public void setDtapWT_In(int Dtap) { + this.DtapWT_In = Dtap; + } + + public void setOtapDL_In(int Otap) { + this.OtapDL_In = Otap; + } + + public void setDtapDL_In(int Dtap) { + this.DtapDL_In = Dtap; + } + + public void setOtapDP_In(int Otap) { + this.OtapDP_In = Otap; + } + + public void setDtapDP_In(int Dtap) { + this.DtapDP_In = Dtap; + } + + public float getGenCostWT_Out() { + return genCostWT_Out; + } + + public float getGenCostDL_Out() { + return genCostDL_Out; + } + + public float getGenCostDP_Out() { + return genCostDP_Out; + } + + public int getOtapWT_Out() { + return OtapWT_Out; + } + + public int getDtapWT_Out() { + return DtapWT_Out; + } + + public int getOtapDL_Out() { + return OtapDL_Out; + } + + public int getDtapDL_Out() { + return DtapDL_Out; + } + + public int getOtapDP_Out() { + return OtapDP_Out; + } + + public int getDtapDP_Out() { + return DtapDP_Out; + } + + public void setGenCostWT_Out(float genCost) { + this.genCostWT_Out = genCost; + } + + public void setGenCostDL_Out(float genCost) { + this.genCostDL_Out = genCost; + } + + public void setGenCostDP_Out(float genCost) { + this.genCostDP_Out = genCost; + } + + public void setOtapWT_Out(int Otap) { + this.OtapWT_Out = Otap; + } + + public void setDtapWT_Out(int Dtap) { + this.DtapWT_Out = Dtap; + } + + public void setOtapDL_Out(int Otap) { + this.OtapDL_Out = Otap; + } + + public void setDtapDL_Out(int Dtap) { + this.DtapDL_Out = Dtap; + } + + public void setOtapDP_Out(int Otap) { + this.OtapDP_Out = Otap; + } + + public void setDtapDP_Out(int Dtap) { + this.DtapDP_Out = Dtap; + } + + /** + * get skim period for tour departure interval + */ + public int getTodOut() { + return modelStructure.getTod( tour.getTourDepartPeriod() ); + } + + /** + * get skim period for tour arrival interval + */ + public int getTodIn() { + return modelStructure.getTod( tour.getTourArrivePeriod() ); + } + + /** + * Set this index values for this tour mode choice DMU object. + * + * @param hhIndex is the DMU household index + * @param zoneIndex is the DMU zone index + * @param origIndex is the DMU origin index + * @param destIndex is the DMU desatination index + */ + public void setDmuIndexValues(int hhIndex, int zoneIndex, int origIndex, int destIndex, boolean debug) + { + dmuIndex.setHHIndex(hhIndex); + dmuIndex.setZoneIndex(zoneIndex); + dmuIndex.setOriginZone(origIndex); + dmuIndex.setDestZone(destIndex); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel(""); + if (debug) + { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel("Debug MC UEC"); + } + + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + public void setIndexDest( int d ) { + dmuIndex.setDestZone( d ); + } + + public void setTourDestTaz( int d ) { + tour.setTourDestTaz( d ); + } + + public void setTourDestWalkSubzone( int subzone ) { + tour.setTourDestWalkSubzone( subzone ); + } + + public void setTourOrigTaz( int o ) { + tour.setTourOrigTaz( o ); + } + + public void setTourDepartPeriod( int period) { + tour.setTourDepartPeriod(period); + } + + public void setTourArrivePeriod( int period) { + tour.setTourArrivePeriod(period); + } + + public void setTourOrigWalkSubzone( int subzone ) { + tour.setTourOrigWalkSubzone( subzone ); + } + + public int getWorkTourModeIsSOV() { + boolean tourModeIsSov = modelStructure.getTourModeIsSov( workTour.getTourModeChoice() ); + return tourModeIsSov ? 1 : 0; + } + + public int getWorkTourModeIsBike() { + boolean tourModeIsBike = modelStructure.getTourModeIsBike( workTour.getTourModeChoice() ); + return tourModeIsBike ? 1 : 0; + } + + //tour mode to and from work + public int getWorkTourMode() { + return workTour.getTourModeChoice(); + } + + + public int getSubtourType() { + return tour.getTourPrimaryPurposeIndex(); + } + + public int getTourCategoryJoint() { + if ( tour.getTourCategoryIsJointNonMandatory() ) + return 1; + else + return 0; + } + + public int getTourCategorySubtour() { + if ( tour.getTourCategoryIsAtWork() ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeEscort() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getEscortPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeShopping() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getShoppingPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeEatOut() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getEatOutPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeSocial() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getSocialPurposeName() ) ) + return 1; + else + return 0; + } + + public int getTourPrimaryPurposeOthDiscr() { + if ( tour.getTourPrimaryPurpose().equalsIgnoreCase( modelStructure.getOthDiscrPurposeName() ) ) + return 1; + else + return 0; + } + + + public int getNumberOfParticipantsInJointTour() { + byte[] participants = tour.getPersonNumArray(); + int returnValue = 0; + if ( participants != null ) + returnValue = participants.length; + return returnValue; + } + + public int getAgeUnder40() { + if ( person.getAge() < 40 ) + return 1; + else + return 0; + } + + public int getAge40to59() { + if ( person.getAge() >= 40 && person.getAge() < 60 ) + return 1; + else + return 0; + } + + public int getAge60to79() { + if ( person.getAge() >= 60 && person.getAge() < 79 ) + return 1; + else + return 0; + } + + public int getAge60plus() { + if ( person.getAge() >= 60 ) + return 1; + else + return 0; + } + + public int getPersonIsWorker() { + return person.getPersonIsWorker(); + } + + public int getPersonIsPartTimeWorker() { + return person.getPersonIsPartTimeWorker(); + } + + public int getPersonIsNonWorkingAdult() { + if ( person.getPersonIsNonWorkingAdultUnder65() == 1 ) + return 1; + else + return 0; + } + + public int getPersonIsMale() { + if ( person.getPersonIsMale() == 1 ) + return 1; + else + return 0; + } + + + public int getPreDrivingChildInHh() { + if ( hh.getNumChildrenUnder16() > 0 ) + return 1; + else + return 0; + } + + public int getNumFemalesInHh() { + int count = 0; + PersonIf[] persons = hh.getPersons(); + for (int i=1; i < persons.length; i++){ + if ( persons[i].getPersonIsFemale() == 1 ) + count++; + } + return count; + } + + public int getFreeParking() { + return person.getFreeParkingAvailableResult(); + } + + public int getHhSize() { + return hh.getHhSize(); + } + + public int getAutos() { + return hh.getAutoOwnershipModelResult(); + } + + public int getDrivers() { + return hh.getDrivers(); + } + + public int getAge() { + return person.getAge(); + } + + public int getHomemaker() { + return person.getHomemaker(); + } + + public int getWorkers() { + return hh.getWorkers(); + } + + public int getOutboundStops() { + return tour.getNumOutboundStops(); + } + + public int getInboundStops() { + return tour.getNumInboundStops(); + } + + public int getSize() { + return hh.getSize(); + } + + public int getGender() { + return person.getGender(); + } + + public int getChildunder16() { + return hh.getChildunder16(); + } + + public int getChild16plus() { + return hh.getChild16plus(); + } + + public int getNumChildrenUnder19() { + return hh.getNumChildrenUnder19(); + } + + public int getNumChildren() { + return hh.getNumChildren(); + } + + public int getNumPreschool() { + return hh.getNumPreschool(); + } + + public int getNumPersons6to15() { + return hh.getNumPersons6to15(); + } + + public int getTourDepartsAfter4pm() { + if ( tour.getTourDepartPeriod() >= modelStructure.getIntervalFor4Pm() ) + return 1; + else + return 0; + } + + public int getTourArrivesAfter7pm() { + if ( tour.getTourArrivePeriod() >= modelStructure.getIntervalFor7Pm() ) + return 1; + else + return 0; + } + + public float getValueOfTime() { + return person.getValueOfTime(); + } + + public boolean getTourModeIsWalkLocal( int tourMode ) { + return(modelStructure.getTourModeIsWalkLocal(tourMode)); + } + + public boolean getTourModeIsDriveTransit( int tourMode ) { + return(modelStructure.getTourModeIsDriveTransit(tourMode)); + } + + public float getHouseholdMaxValueOfTime() { + + float max_hh_vot = 0; + + PersonIf[] persons = hh.getPersons(); + for (int i=1; i < persons.length; i++){ + float per_vot = persons[i].getValueOfTime(); + if(per_vot > max_hh_vot) { max_hh_vot = per_vot; } + } + + return max_hh_vot; + } + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/TravelTimeModel.java b/src/java/com/pb/models/ctrampIf/TravelTimeModel.java new file mode 100644 index 0000000..72366f8 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TravelTimeModel.java @@ -0,0 +1,112 @@ +package com.pb.models.ctrampIf; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.jppf.*; +import com.pb.common.newmodel.ChoiceModelApplication; +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author crf + * Started Nov 4, 2010 1:55:52 PM + */ +public class TravelTimeModel { + private static final int TT_DATA_SHEET = 0; + private static final int TT_PEAK_SHEET = 1; + private static final int TT_OFFPEAK_SHEET = 2; + private static final String PROPERTIES_UEC_TRAVEL_TIME_MODEL = "UecFile.TravelTime"; + + private static final String[] timePeriods = {"peak","offpeak"}; + private static final int START_AM_PEAK = 6; + private static final int END_AM_PEAK = 9; + private static final int START_PM_PEAK = 15; + private static final int END_PM_PEAK = 18; + + private final ChoiceModelApplication peakModel; + private final ChoiceModelApplication offPeakModel; + private final TravelTimeDMU modelDmu; + private final IndexValues indices; + private final Map peakModeToAlternativeMap; + private final Map offPeakModeToAlternativeMap; + + public TravelTimeModel(HashMap propertyMap) { + String mcUecFile = propertyMap.get(com.pb.models.ctrampIf.jppf.CtrampApplication.PROPERTIES_PROJECT_DIRECTORY) + + propertyMap.get(PROPERTIES_UEC_TRAVEL_TIME_MODEL); + + modelDmu = new TravelTimeDMU(); + indices = new IndexValues(); + peakModel = new ChoiceModelApplication(mcUecFile,TT_PEAK_SHEET,TT_DATA_SHEET,propertyMap,modelDmu); + offPeakModel = new ChoiceModelApplication(mcUecFile,TT_OFFPEAK_SHEET,TT_DATA_SHEET,propertyMap,modelDmu); + peakModeToAlternativeMap = new HashMap(); + String[] alts = peakModel.getAlternativeNames(); + for (int i = 0; i < alts.length; i++) + peakModeToAlternativeMap.put(alts[i].toLowerCase(),i); + offPeakModeToAlternativeMap = new HashMap(); + alts = offPeakModel.getAlternativeNames(); + for (int i = 0; i < alts.length; i++) + offPeakModeToAlternativeMap.put(alts[i].toLowerCase(),i); + } + + private boolean tripStartsInPeakPeriod(int startHour) { + return ((startHour >= START_AM_PEAK && startHour <= END_AM_PEAK) || + (startHour >= START_PM_PEAK && startHour <= END_PM_PEAK)); + } + + private double getTravelTime(int origin, int dest, Boolean peak, String alt) { + indices.setOriginZone(origin); + indices.setDestZone(dest); + ChoiceModelApplication app = peak ? peakModel : offPeakModel; + app.computeUtilities(modelDmu,indices); + return app.getUtilities()[(peak ? peakModeToAlternativeMap : offPeakModeToAlternativeMap).get(alt)]; + + } + + public String[] getAlternatives(String period) { + return (period == timePeriods[0]) ? peakModel.getAlternativeNames() : offPeakModel.getAlternativeNames(); + } + + public String[] getTimePeriods() { + return timePeriods; + } + public double[] getTravelTimes(String period, int origin, int dest) { + indices.setOriginZone(origin); + indices.setDestZone(dest); + ChoiceModelApplication app = (period == timePeriods[0]) ? peakModel : offPeakModel; + app.computeUtilities(modelDmu,indices); + return app.getUtilities(); + } + + public double getTravelTime(String modeName, int startHour, int origin, int dest) { + return getTravelTime(origin,dest,tripStartsInPeakPeriod(startHour),modeName.toLowerCase()); + } + + private class TravelTimeDMU implements VariableTable { + + public int getIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/src/java/com/pb/models/ctrampIf/TripMatrixWriterIf.java b/src/java/com/pb/models/ctrampIf/TripMatrixWriterIf.java new file mode 100644 index 0000000..d7fd8a2 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TripMatrixWriterIf.java @@ -0,0 +1,10 @@ +package com.pb.models.ctrampIf; + +/** + * @author bts + */ +public interface TripMatrixWriterIf { + + public abstract void writeMatrices(); + +} diff --git a/src/java/com/pb/models/ctrampIf/TripModeChoiceDMU.java b/src/java/com/pb/models/ctrampIf/TripModeChoiceDMU.java new file mode 100644 index 0000000..aec3b42 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/TripModeChoiceDMU.java @@ -0,0 +1,402 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; + +public class TripModeChoiceDMU implements Serializable, VariableTable { + + protected transient Logger logger = Logger.getLogger(TripModeChoiceDMU.class); + + protected HashMap methodIndexMap; + + protected StopIf stop; + protected TourIf tour; + protected PersonIf person; + protected HouseholdIf hh; + protected IndexValues dmuIndex; + + protected int origType; + protected int destType; + protected float origParkRate; + protected float primDestParkRate; + protected float intStopParkRate; + + protected int stopIsFirst; + protected int stopIsLast; + + + private ModelStructure modelStructure; + + int[] tazForMaz; + + float genCostWT; + float genCostDL; + float genCostDP; + int OtapWT; + int DtapWT; + int OtapDL; + int DtapDL; + int OtapDP; + int DtapDP; + + TazDataIf tazDataManager; + + public TripModeChoiceDMU(TazDataIf tazDataManager, ModelStructure modelStructure ){ + this.modelStructure = modelStructure; + dmuIndex = new IndexValues(); + + tazForMaz = tazDataManager.getTazsForMazs(); + + this.tazDataManager = tazDataManager; + } + + + + public HouseholdIf getHouseholdObject() { + return hh; + } + + public TourIf getTourObject() { + return tour; + } + + public int getTodOut() { + return modelStructure.getTod( stop.getStopPeriod() ); + } + + public void setHouseholdObject ( HouseholdIf hhObject ) { + hh = hhObject; + } + + public void setPersonObject ( PersonIf personObject ) { + person = personObject; + } + + public void setTourObject ( TourIf tourObject ) { + tour = tourObject; + } + + public void setStopObject ( StopIf stopObject ) { + stop = stopObject; + } + + public void setStopObjectIsFirst ( int flag ) { + stopIsFirst = flag; + } + + public void setStopObjectIsLast ( int flag ) { + stopIsLast = flag; + } + + + + public int getOmazOtaz() { + return tazForMaz[dmuIndex.getOriginZone()-1]; + } + + public int getDmazDtaz() { + return tazForMaz[dmuIndex.getDestZone()-1]; + } + + public float getGenCostWT() { + return genCostWT; + } + + public float getGenCostDL() { + return genCostDL; + } + + public float getGenCostDP() { + return genCostDP; + } + + public int getOtapWT() { + return OtapWT; + } + + public int getDtapWT() { + return DtapWT; + } + + public int getOtapDL() { + return OtapDL; + } + + public int getDtapDL() { + return DtapDL; + } + + public int getOtapDP() { + return OtapDP; + } + + public int getDtapDP() { + return DtapDP; + } + + public void setGenCostWT(float genCost) { + this.genCostWT = genCost; + } + + public void setGenCostDL(float genCost) { + this.genCostDL = genCost; + } + + public void setGenCostDP(float genCost) { + this.genCostDP = genCost; + } + + public void setOtapWT(int Otap) { + this.OtapWT = Otap; + } + + public void setDtapWT(int Dtap) { + this.DtapWT = Dtap; + } + + public void setOtapDL(int Otap) { + this.OtapDL = Otap; + } + + public void setDtapDL(int Dtap) { + this.DtapDL = Dtap; + } + + public void setOtapDP(int Otap) { + this.OtapDP = Otap; + } + + public void setDtapDP(int Dtap) { + this.DtapDP = Dtap; + } + + public double getOMazDMazDistance() { + return tazDataManager.getOMazDMazDistance(dmuIndex.getOriginZone(), dmuIndex.getDestZone()); + } + + + // DMU methods - define one of these for every @var in the mode choice control file. + + public void setDmuIndexValues( int hhId, int origTaz, int destTaz ) { + dmuIndex.setHHIndex( hhId ); + dmuIndex.setZoneIndex( destTaz ); + dmuIndex.setOriginZone( origTaz ); + dmuIndex.setDestZone( destTaz ); + + dmuIndex.setDebug(false); + dmuIndex.setDebugLabel ( "" ); + if ( hh.getDebugChoiceModels() ) { + dmuIndex.setDebug(true); + dmuIndex.setDebugLabel ( "Debug Trip MC UEC" ); + } + + } + + + /** + * origin type is 1 if home, 2 if primary dest, 3 if intermediate stop, for home-based tours. + * origin type is 1 if work, 2 if primary dest, 3 if intermediate stop, for work-based tours. + */ + public void setOrigType( int type ) { + origType = type; + } + + /** + * destination type is 1 if home, 2 if primary dest, 3 if intermediate stop, for home-based tours. + * destination type is 1 if work, 2 if primary dest, 3 if intermediate stop, for work-based tours. + */ + public void setDestType( int type ) { + destType = type; + } + + public void setOrigParkRate( float cost ) { + origParkRate = cost; + } + + public void setIntStopParkRate( float cost ) { + intStopParkRate = cost; + } + + public void setPrimDestParkRate( float cost ) { + primDestParkRate = cost; + } + + + public int getFreeParking() { + return person.getFreeParkingAvailableResult(); + } + + + public int getOrigType() { + return origType; + } + + public int getDestType() { + return destType; + } + + public float getOrigParkRate() { + return origParkRate; + } + + public float getIntStopParkRate() { + return intStopParkRate; + } + + public float getPrimDestParkRate() { + return primDestParkRate; + } + + public IndexValues getDmuIndexValues() { + return dmuIndex; + } + + + public int getZonalShortWalkAccessOrig() { + if ( stop.getOrigWalkSegment() == 1 ) + return 1; + else + return 0; + } + + public int getZonalShortWalkAccessDest() { + if ( stop.getDestWalkSegment() == 1 ) + return 1; + else + return 0; + } + + public int getZonalLongWalkAccessOrig() { + if ( stop.getOrigWalkSegment() == 2 ) + return 1; + else + return 0; + } + + public int getZonalLongWalkAccessDest() { + if ( stop.getDestWalkSegment() == 2 ) + return 1; + else + return 0; + } + + + public int getTourCategoryJoint() { + if ( tour.getTourCategoryIsJointNonMandatory() ) + return 1; + else + return 0; + } + + public int getTourCategorySubtour() { + if ( tour.getTourCategoryIsAtWork() ) + return 1; + else + return 0; + } + + public int getTourModeIsAuto() { + boolean tourModeIsAuto = modelStructure.getTourModeIsSovOrHov( tour.getTourModeChoice() ); + return tourModeIsAuto ? 1 : 0; + } + + public int getTourModeIsWalkTransit() { + boolean tourModeIsWalkLocal = modelStructure.getTourModeIsWalkLocal( tour.getTourModeChoice() ); + boolean tourModeIsWalkPremium = modelStructure.getTourModeIsWalkPremium( tour.getTourModeChoice() ); + return tourModeIsWalkLocal || tourModeIsWalkPremium ? 1 : 0; + } + + public int getTourModeIsDriveTransit() { + boolean tourModeIsDriveTransit = modelStructure.getTourModeIsDriveTransit( tour.getTourModeChoice() ); + return tourModeIsDriveTransit ? 1 : 0; + } + + public int getWorkTourModeIsSOV() { + boolean workTourModeIsSov = modelStructure.getTourModeIsSov( tour.getTourModeChoice() ); + return workTourModeIsSov ? 1 : 0; + } + + public int getWorkTourModeIsBike() { + boolean tourModeIsBike = modelStructure.getTourModeIsBike( tour.getTourModeChoice() ); + return tourModeIsBike ? 1 : 0; + } + + public int getTourModeIsSOV() { + boolean tourModeIsSov = modelStructure.getTourModeIsSov( tour.getTourModeChoice() ); + return tourModeIsSov ? 1 : 0; + } + + public int getTourModeIsBike() { + boolean tourModeIsBike = modelStructure.getTourModeIsBike( tour.getTourModeChoice() ); + return tourModeIsBike ? 1 : 0; + } + + public int getTourModeIsWalk() { + boolean tourModeIsWalk = modelStructure.getTourModeIsWalk( tour.getTourModeChoice() ); + return tourModeIsWalk ? 1 : 0; + } + + public int getTourMode() { + return tour.getTourModeChoice(); + } + + public int getSubtourType() { + return tour.getTourPrimaryPurposeIndex(); + } + + + public int getNumberOfParticipantsInJointTour() { + return tour.getPersonNumArray().length; + } + + + public boolean getModeIsWalkLocal( int mode ) { + return(modelStructure.getTourModeIsWalkLocal(mode)); + } + + public boolean getModeIsDriveTransit( int mode ) { + return(modelStructure.getTourModeIsDriveTransit(mode)); + } + + public int getStopIsFirst() { + return stopIsFirst; + } + + public int getStopIsLast() { + return stopIsLast; + } + + + public int getIndexValue(String variableName) { + return methodIndexMap.get(variableName); + } + + + + + public int getAssignmentIndexValue(String variableName) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex) { + throw new UnsupportedOperationException(); + } + + public double getValueForIndex(int variableIndex, int arrayIndex) { + throw new UnsupportedOperationException(); + } + + public void setValue(String variableName, double variableValue) { + throw new UnsupportedOperationException(); + } + + public void setValue(int variableIndex, double variableValue) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/Util.java b/src/java/com/pb/models/ctrampIf/Util.java new file mode 100644 index 0000000..20565d1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/Util.java @@ -0,0 +1,91 @@ +package com.pb.models.ctrampIf; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.StringTokenizer; +import org.apache.log4j.Logger; + +public class Util + implements Serializable +{ + + private static Logger logger = Logger.getLogger(Util.class); + + public static boolean getBooleanValueFromPropertyMap(HashMap rbMap, String key) + { + boolean returnValue; + String value = rbMap.get(key); + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) + { + returnValue = Boolean.parseBoolean(value); + } else + { + logger.error("property file key: " + key + " = " + value + + " should be either 'true' or 'false'."); + throw new RuntimeException(); + } + + return returnValue; + } + + public static String getStringValueFromPropertyMap(HashMap rbMap, String key) + { + String returnValue = rbMap.get(key); + if (returnValue == null) returnValue = ""; + + return returnValue; + } + + public static int getIntegerValueFromPropertyMap(HashMap rbMap, String key) + { + String value = rbMap.get(key); + if (value != null) + { + return Integer.parseInt(value); + } else + { + logger.error("property file key: " + key + + " missing. No integer value can be determined."); + throw new RuntimeException(); + } + } + + public static int[] getIntegerArrayFromPropertyMap(HashMap rbMap, String key) + { + + int[] returnArray; + String valueList = rbMap.get(key); + if (valueList != null) + { + + HashSet valueSet = new HashSet(); + + if (valueSet != null) + { + StringTokenizer valueTokenizer = new StringTokenizer(valueList, ","); + while(valueTokenizer.hasMoreTokens()) + { + String listValue = valueTokenizer.nextToken(); + int intValue = Integer.parseInt(listValue.trim()); + valueSet.add(intValue); + } + } + + returnArray = new int[valueSet.size()]; + int i = 0; + for (int v : valueSet) + returnArray[i++] = v; + + } else + { + logger.error("property file key: " + key + + " missing. No integer value can be determined."); + throw new RuntimeException(); + } + + return returnArray; + + } + +} diff --git a/src/java/com/pb/models/ctrampIf/UtilRmi.java b/src/java/com/pb/models/ctrampIf/UtilRmi.java new file mode 100644 index 0000000..ff758cc --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/UtilRmi.java @@ -0,0 +1,161 @@ +package com.pb.models.ctrampIf; + +import gnu.cajo.invoke.Remote; + +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.rmi.ConnectIOException; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.io.IOException; + +import org.apache.log4j.Logger; + +/** + * User: Jim + * Date: Jul 3, 2008 + * Time: 2:27:02 PM + * + * Utility class for applying remote methods of various types + * + */ + +public class UtilRmi implements java.io.Serializable { + + + private transient Logger logger = Logger.getLogger(UtilRmi.class); + private String connectString; + + private static int MAX_RETRY_COUNT = 100; + private static int MAX_RETRY_TIME = 1000; // milliseconds + + private static final int VERSION_TRACKING = 1; + + + public UtilRmi(String connectString) { + this.connectString = connectString; + } + + + + public Object method( String name, Object[] args ) { + + int connectExceptionCount = 0; + + Object itemObject = null; + Object returnObject = null; + + + while ( connectExceptionCount < MAX_RETRY_COUNT ) { + + try { + itemObject = Remote.getItem(connectString); + break; + } + catch (ConnectIOException e) { + + try { + Thread.currentThread().wait( MAX_RETRY_TIME ); + } catch (InterruptedException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + connectExceptionCount++; + + } + catch (RemoteException e) { + logger.error ("RemoteException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (MalformedURLException e) { + logger.error ("MalformedURLException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (NotBoundException e) { + logger.error ("NotBoundException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (IOException e) { + logger.error ("IOException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (ClassNotFoundException e) { + logger.error ("ClassNotFoundException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (InstantiationException e) { + logger.error ("InstantiationException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (IllegalAccessException e) { + logger.error ("IllegalAccessException exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + catch (UnsatisfiedLinkError e) { + logger.error ("UnsatisfiedLinkError exception making RMI method call: " + connectString + "." + name + "().", e); + throw new RuntimeException(); + } + + } + + + if ( connectExceptionCount > 0 ) { + logger.warn ("UtilRmi.method() timed out " + connectExceptionCount + "times connecting to: " + connectString + "." + name + "()." ); + } + if ( connectExceptionCount == MAX_RETRY_COUNT ) { + logger.error ("UtilRmi.method() connection was never made." ); + throw new RuntimeException(); + } + + + + try { + returnObject = Remote.invoke( itemObject, name, args ); + } + catch (InvocationTargetException e) { + + Logger logger = Logger.getLogger(UtilRmi.class); + + logger.error( "version tracking number = " + VERSION_TRACKING + "." ); + logger.error ("InvocationTargetException exception making RMI method call."); + logger.error ("itemObject " + (itemObject == null ? "is" : "is not") + " null."); + logger.error ("name " + (name == null ? "is" : "is not") + " null."); + logger.error ("args " + (args == null ? "is" : "is not") + " null."); + if ( connectString != null ) + logger.error ("connectString = " + connectString + "."); + else + logger.error ("connectString is null."); + if ( name != null ) + logger.error ("name = " + name + "."); + + logger.error ("stack trace", e); + System.exit(-20); + } + catch (Exception e) { + + Logger logger = Logger.getLogger(UtilRmi.class); + + logger.error( "version tracking number = " + VERSION_TRACKING + "." ); + + logger.error ("Other exception making RMI method call."); + logger.error ("itemObject " + (itemObject == null ? "is" : "is not") + " null."); + logger.error ("name " + (name == null ? "is" : "is not") + " null."); + logger.error ("args " + (args == null ? "is" : "is not") + " null."); + if ( connectString != null ) + logger.error ("connectString = " + connectString + "."); + else + logger.error ("connectString is null."); + if ( name != null ) + logger.error ("name = " + name + "."); + + logger.error ("stack trace", e); + System.exit(-21); + } + + return returnObject; + + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/AutoDependencyModel.java b/src/java/com/pb/models/ctrampIf/jppf/AutoDependencyModel.java new file mode 100644 index 0000000..f46f02b --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/AutoDependencyModel.java @@ -0,0 +1,163 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.*; + +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; + +import org.apache.log4j.Logger; + +public class AutoDependencyModel implements Serializable { + + private transient Logger logger = Logger.getLogger(AutoDependencyModel.class); + private transient Logger aoLogger = Logger.getLogger("ao"); + + public static final String PROPERTIES_UEC_AUTO_DEPENDENCY = "UecFile.AutoDependency"; + private static final int DATA_SHEET = 0; + private static final int WORK_MODEL_SHEET = 1; + private static final int UNIVERSITY_MODEL_SHEET = 2; + private static final int SCHOOL_MODEL_SHEET = 3; + private static final int[] MODEL_SHEETS = {WORK_MODEL_SHEET, UNIVERSITY_MODEL_SHEET, SCHOOL_MODEL_SHEET}; + private String[] tourPurposeList = new String[MODEL_SHEETS.length]; + private static final int[] NON_AUTO_ALTS = {3,5,8,10}; //1-based + + // A MyChoiceModelApplication object and modeAltsAvailable[] is needed for each purpose + private ChoiceModelApplication adModel[]; + private TourModeChoiceDMU mcDmuObject; + + private String tourCategory; + private HashMap purposeModelIndexMap; + + + public AutoDependencyModel( HashMap propertyMap, ModelStructure modelStructure, String tourCategory, CtrampDmuFactoryIf dmuFactory ){ + + this.tourCategory = tourCategory; + mcDmuObject = dmuFactory.getModeChoiceDMU(); + setupAutoDependencyModelApplicationArray( propertyMap, modelStructure, tourCategory ); + } + + private void setupAutoDependencyModelApplicationArray( HashMap propertyMap, ModelStructure modelStructure, String tourCategory ) { + + logger.info( String.format( "setting up %s auto dependency model.", tourCategory ) ); + + // locate the auto dependency model UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String adUecFile = propertyMap.get( PROPERTIES_UEC_AUTO_DEPENDENCY ); + adUecFile = projectDirectory + adUecFile; + + //get tour purpose names + tourPurposeList[0] = ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase(); + tourPurposeList[1] = ModelStructure.UNIVERSITY_PRIMARY_PURPOSE_NAME.toLowerCase(); + tourPurposeList[2] = ModelStructure.SCHOOL_PRIMARY_PURPOSE_NAME.toLowerCase(); + + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + for ( int i=0; i it = modelIndexSet.iterator(); + while ( it.hasNext() ) { + int m = it.next(); + adModel[m] = new ChoiceModelApplication ( adUecFile, m, DATA_SHEET, propertyMap, (VariableTable)mcDmuObject ); + } + } + + /** + * Calculate and return the logsum for the DMU object. + * @param mcDmuObject is the tour mode choice model DMU object + * @param solveForAutoModesOnly if true sets non-auto modes to not avail + * @return logsum + */ + public double getLogsum ( TourModeChoiceDMU mcDmuObject, String primaryPurposeName, Logger modelLogger, String choiceModelDescription, String decisionMakerLabel, boolean solveForAutoModesOnly) { + + int modelIndex = purposeModelIndexMap.get( primaryPurposeName.toLowerCase() ); + + HouseholdIf household = mcDmuObject.getHouseholdObject(); + + // log headers to traceLogger + if ( household.getDebugChoiceModels() ) { + adModel[modelIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + } + + //set availabilities, calculate utilities and get logsum + boolean[] avail = adModel[modelIndex].getAvailabilities(); //index=0 is empty since array starts at 1 + int[] sample = new int[avail.length]; + + if(solveForAutoModesOnly) { + + //set all available + for(int i=0; i 1), + // that number of lines follows the alternatives names to define the nesting structure, + // then the same number of lines follows those to define the nesting coefficients. + + if ( header.numberOfLevels > 1 ) { + + nestedAlternatives = new int[header.numberOfLevels][header.numberOfAlts]; + + for (int r=0; r < header.numberOfLevels; r++) { + + row++; + + for (int col=0; col < header.numberOfAlts; col++) { + Cell cell = sheet.getCell(col+ALTERNATIVE_START_COL, row); + int levelIndex = Integer.parseInt( cell.getContents() ); + nestedAlternatives[r][col] = levelIndex; + + if ( logger.isDebugEnabled()){ + logger.debug( String.format ("level%d: col=%d, index=%d", r, col, levelIndex) ); + } + } + + } + + + nestingCoefficients = new double[header.numberOfLevels][header.numberOfAlts]; + + for (int r=0; r < header.numberOfLevels; r++) { + + row++; + + for (int col=0; col < header.numberOfAlts; col++) { + Cell cell = sheet.getCell(col+ALTERNATIVE_START_COL, row); + try { + nestingCoefficients[r][col] = Double.parseDouble( cell.getContents() ); + } + catch ( NumberFormatException e ){ + nestingCoefficients[r][col] = 0.0; + } + + if ( logger.isDebugEnabled()){ + logger.debug( String.format ("level%d: col=%d, index=%.6f", r, col, nestingCoefficients[r][col]) ); + } + } + + } + + } + + } + + + /** + * Read the entries for the model record. + */ + protected void readModelEntries() { + + Sheet sheet = workbook.getSheet( modelSheet ); + + int row; + row = findEntry(sheet, "Model", 0, 0, true); + row = findEntry(sheet, "1", row, 0, true); + + Cell cell; + + //Temporary lists. We don't know how many entries there are. + ArrayList entryList = new ArrayList(); + ArrayList coeffList = new ArrayList(); + + while (true) { + + //Check for end of input + if ( row == sheet.getRows() ) { + break; + } + + cell = sheet.getCell(0, row); + String number = cell.getContents(); + + //Check for end of input + if ( (number == null) || (number.length() == 0) ) { + break; + } + + cell = sheet.getCell(1, row); + String name = cell.getContents().trim(); + + cell = sheet.getCell(2, row); + String description = cell.getContents(); + + cell = sheet.getCell(3, row); + String filter = cell.getContents().trim(); + + cell = sheet.getCell(4, row); + String expression = cell.getContents().trim(); + + cell = sheet.getCell(5, row); + String index = cell.getContents().trim(); + + //Add entry object to array list (temporarily) + ModelEntry entry = new ModelEntry(name, description, filter, expression, index); + entryList.add( entry ); + + //Read coefficients for each alternative + float[] coeff = new float[header.numberOfAlts]; + + for (int col=0; col < header.numberOfAlts; col++) { + cell = sheet.getCell(col+ALTERNATIVE_START_COL, row); + String str = cell.getContents(); + if ( (str != null) && (str.length() > 0) ) + coeff[col] = Float.parseFloat( str.trim() ); + else + coeff[col] = 0; + + } + coeffList.add( coeff ); + + row++; + } + + //Convert array list of entries to an array + modelEntries = new ModelEntry[entryList.size()]; + for (int r=0; r < entryList.size(); r++) { + modelEntries[r] = (ModelEntry) entryList.get(r); + } + + //Convert array list of coeffcients to an array of float + coefficients = new float[coeffList.size()][header.numberOfAlts]; + for (int r=0; r < coeffList.size(); r++) { + coefficients[r] = (float[]) coeffList.get(r); + } + + if ( logger.isDebugEnabled()){ + for (int r=0; r < coeffList.size(); r++) { + logger.debug("entry: "+modelEntries[r]); + } + + for (int r=0; r < coeffList.size(); r++) { + StringBuffer sb = new StringBuffer(256); + sb.append("coeff:"); + for (int col=0; col < header.numberOfAlts; col++) { + sb.append(" " + coefficients[r][col]); + } + logger.debug(sb.toString()); + } + } + + } + + + protected ArrayList readTableDataEntries() { + + //Holds the entries found in the section + ArrayList dataList = new ArrayList(); + + Cell cell; + + Sheet sheet = workbook.getSheet( dataSheet ); + + int row = findEntry(sheet, "Table Data", 0, 0, false); + int mtxRow = findEntry(sheet, "Matrix Data", 0, 0, false); + + if (row == -1) { + //No Table data section was found + return dataList; + } + + row = findEntry(sheet, "1", row, 0, false); + if (row == -1) { + //No Table data entries were found + return dataList; + } + + if (mtxRow > 0 && row > mtxRow) { + //No Table data entries were found + return dataList; + } + + while (true) { + + cell = sheet.getCell(1, row); + String type = cell.getContents(); + + //Check for end of input + if ( (type == null) || (type.length() == 0) ) { + break; + } + + cell = sheet.getCell(2, row); + String format = cell.getContents(); + format = searchAndReplaceWithEnv( format ); + + + cell = sheet.getCell(3, row); + String fileName = cell.getContents(); + fileName = searchAndReplaceWithEnv( fileName ); + + + //Add entry object to list + DataEntry entry = new DataEntry(type, format, fileName); + dataList.add( entry ); + + row++; + } + + return dataList; + } + + + protected ArrayList readMatrixDataEntries() { + + //Holds entries found in the section + ArrayList matrixList = new ArrayList(); + + Cell cell; + Sheet sheet = workbook.getSheet( dataSheet ); + + int mtxRow = findEntry(sheet, "Matrix Data", 0, 0, false); + if (mtxRow == -1) { + //No Matrix data section was found + return matrixList; + } + + int row = findEntry(sheet, "1", mtxRow, 0, false); + if (row == -1) { + //No Matrix data entries were found + return matrixList; + } + + + while (true) { + + if ( row >= sheet.getRows() ) { + break; + } + + + cell = sheet.getCell(1, row); + String name = cell.getContents(); + + //Check for end of input + if ( (name == null) || (name.length() == 0) ) { + break; + } + + cell = sheet.getCell(2, row); + String format = cell.getContents(); + format = searchAndReplaceWithEnv( format ); + + + cell = sheet.getCell(3, row); + String fileName = cell.getContents(); + + cell = sheet.getCell(4, row); + String matrixName = cell.getContents(); + + cell = sheet.getCell(5, row); + String groupName = cell.getContents(); + + cell = sheet.getCell(6, row); + String indexFlag = cell.getContents(); + + String gName = (groupName == null) ? "" : groupName; + boolean iFlag = ((indexFlag != null) && (indexFlag.trim().length() > 0)) ? true : false; + + fileName = searchAndReplaceWithEnv( fileName ); + + //Add entry object to array list (temporarily) + DataEntry entry = new DataEntry("matrix", name, format, fileName, matrixName, gName, iFlag); + matrixList.add( entry ); + + row++; + } + + return matrixList; + } + + + protected int findEntry(Sheet sheet, String keyword, int startRow, int startColumn, boolean fail) { + int rowFound = -1; + String str; + + try { + for (int r=startRow; r < sheet.getRows(); r++) { + Cell cell = sheet.getCell(startColumn, r); + str = cell.getContents(); + if (str.equalsIgnoreCase(keyword)) { + rowFound = r; + break; + } + } + } catch (RuntimeException e) { + //Did not find keyword + } + + if ( (rowFound < 0) && (fail) ) { + String msg = "Control file does not contain a \""+keyword+"\" section"; + throw new RuntimeException(msg); + } + + /* + if (LogConstants.DEBUG) { + Logger.logDebug("found \""+keyword+"\"on row="+rowFound+", column="+startColumn); + } + */ + + return rowFound; + } + + public ModelHeader getHeader() { + return header; + } + + public ModelEntry[] getModelEntries() { + return modelEntries; + } + + public ModelAlternative[] getAlternatives() { + return alternatives; + } + + public DataEntry[] getTableEntries() { + return tableEntries; + } + + public DataEntry[] getMatrixEntries() { + return matrixEntries; + } + + public float[][] getCoefficients() { + return coefficients; + } + + public int[][] getNestedAlternatives() { + return nestedAlternatives; + } + + public double[][] getNestingCoefficients() { + return nestingCoefficients; + } + + /* + * Search and replace patterns in a string based on values in the environment. + */ + private String searchAndReplaceWithEnv(String inputStr) { + + String tempStr = new String( inputStr ); + + //Check properties defined on command-line first + String replacedString = ResourceUtil.replaceWithSystemPropertyValues(tempStr); + + //Next iterate over properties passed HashMap + Iterator keys = env.keySet().iterator(); + while (keys.hasNext()) { + String name = (String) keys.next(); + String value = (String) env.get(name); + + //If the property is defined on the command-line, it will replace what the user + //passed in the environment (i.e. HashMap) + value = ResourceUtil.checkSystemProperties(name, value); + + String patternStr = "%" + name + "%"; + Pattern pattern = Pattern.compile(patternStr); + + // Replace all occurrences of pattern in input + Matcher matcher = pattern.matcher(replacedString); + replacedString = matcher.replaceAll(value); + } + + if ( logger.isDebugEnabled()) + logger.debug("replacing input string = " + inputStr + ", output string = " + replacedString); + + + if (replacedString.equals("")) + return inputStr; + else + return replacedString; + } + + + public static void main(String[] args) { + ControlFileReader file = new ControlFileReader(new File(args[0]), null, 1, 1); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/CtrampApplication.java b/src/java/com/pb/models/ctrampIf/jppf/CtrampApplication.java new file mode 100644 index 0000000..ac7c0bf --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/CtrampApplication.java @@ -0,0 +1,1843 @@ +package com.pb.models.ctrampIf.jppf; + +import gnu.cajo.invoke.Remote; +import gnu.cajo.utils.ItemServer; + +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.TreeMap; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Serializable; +import java.net.UnknownHostException; + +import org.apache.log4j.Logger; +import org.jppf.client.JPPFClient; + +import com.pb.common.matrix.MatrixType; +import com.pb.common.util.ResourceUtil; +import com.pb.common.calculator.MatrixDataManager; +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.Definitions; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.HouseholdDataWriter; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.MatrixDataServer; +import com.pb.models.ctrampIf.MatrixDataServerRmi; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.StopFrequencyDMU; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.TripMatrixWriterIf; +import com.pb.models.synpopV3.PopulationSynthesizer; + + + + +public class CtrampApplication implements Serializable { + + private Logger logger = Logger.getLogger(CtrampApplication.class); + + + public static final String VERSION = "1.0"; + + + public static final int MATRIX_DATA_SERVER_PORT = 1171; + + + + public static final String PROPERTIES_BASE_NAME = "ctramp"; + public static final String PROPERTIES_PROJECT_DIRECTORY = "Project.Directory"; + public static final String PROPERTIES_UEC_PATH = "uec.path"; + + public static final String SQLITE_DATABASE_FILENAME = "Sqlite.DatabaseFileName"; + + public static final String PROPERTIES_RUN_POPSYN = "RunModel.PopulationSynthesizer"; + public static final String PROPERTIES_RUN_WORKSCHOOL_CHOICE = "RunModel.UsualWorkAndSchoolLocationChoice"; + public static final String PROPERTIES_RUN_AUTO_OWNERSHIP = "RunModel.AutoOwnership"; + public static final String PROPERTIES_RUN_FREE_PARKING_AVAILABLE = "RunModel.FreeParking"; + public static final String PROPERTIES_RUN_DAILY_ACTIVITY_PATTERN = "RunModel.CoordinatedDailyActivityPattern"; + public static final String PROPERTIES_RUN_INDIV_MANDATORY_TOUR_FREQ = "RunModel.IndividualMandatoryTourFrequency"; + public static final String PROPERTIES_RUN_MAND_TOUR_DEP_TIME_AND_DUR = "RunModel.MandatoryTourDepartureTimeAndDuration"; + public static final String PROPERTIES_RUN_MAND_TOUR_MODE_CHOICE = "RunModel.MandatoryTourModeChoice"; + public static final String PROPERTIES_RUN_AT_WORK_SUBTOUR_FREQ = "RunModel.AtWorkSubTourFrequency"; + public static final String PROPERTIES_RUN_AT_WORK_SUBTOUR_LOCATION_CHOICE = "RunModel.AtWorkSubTourLocationChoice"; + public static final String PROPERTIES_RUN_AT_WORK_SUBTOUR_MODE_CHOICE = "RunModel.AtWorkSubTourModeChoice"; + public static final String PROPERTIES_RUN_AT_WORK_SUBTOUR_DEP_TIME_AND_DUR = "RunModel.AtWorkSubTourDepartureTimeAndDuration"; + public static final String PROPERTIES_RUN_JOINT_TOUR_FREQ = "RunModel.JointTourFrequency"; + public static final String PROPERTIES_RUN_JOINT_LOCATION_CHOICE = "RunModel.JointTourLocationChoice"; + public static final String PROPERTIES_RUN_JOINT_TOUR_MODE_CHOICE = "RunModel.JointTourModeChoice"; + public static final String PROPERTIES_RUN_JOINT_TOUR_DEP_TIME_AND_DUR = "RunModel.JointTourDepartureTimeAndDuration"; + public static final String PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_FREQ = "RunModel.IndividualNonMandatoryTourFrequency"; + public static final String PROPERTIES_RUN_INDIV_NON_MANDATORY_LOCATION_CHOICE = "RunModel.IndividualNonMandatoryTourLocationChoice"; + public static final String PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_MODE_CHOICE = "RunModel.IndividualNonMandatoryTourModeChoice"; + public static final String PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_DEP_TIME_AND_DUR = "RunModel.IndividualNonMandatoryTourDepartureTimeAndDuration"; + public static final String PROPERTIES_RUN_STOP_FREQUENCY = "RunModel.StopFrequency"; + public static final String PROPERTIES_RUN_STOP_LOCATION = "RunModel.StopLocation"; + + + public static final String PROPERTIES_UEC_AUTO_OWNERSHIP = "UecFile.AutoOwnership"; + public static final String PROPERTIES_UEC_DAILY_ACTIVITY_PATTERN = "UecFile.CoordinatedDailyActivityPattern"; + public static final String PROPERTIES_UEC_INDIV_MANDATORY_TOUR_FREQ = "UecFile.IndividualMandatoryTourFrequency"; + public static final String PROPERTIES_UEC_MAND_TOUR_DEP_TIME_AND_DUR = "UecFile.TourDepartureTimeAndDuration"; + public static final String PROPERTIES_UEC_INDIV_NON_MANDATORY_TOUR_FREQ = "UecFile.IndividualNonMandatoryTourFrequency"; + + // TODO eventually move to model-specific structure object + public static final int TOUR_MODE_CHOICE_WORK_MODEL_UEC_PAGE = 1; + public static final int TOUR_MODE_CHOICE_UNIVERSITY_MODEL_UEC_PAGE = 2; + public static final int TOUR_MODE_CHOICE_HIGH_SCHOOL_MODEL_UEC_PAGE = 3; + public static final int TOUR_MODE_CHOICE_GRADE_SCHOOL_MODEL_UEC_PAGE = 4; + + // TODO eventually move to model-specific model structure object + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_WORK_MODEL_UEC_PAGE = 1; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_WORK_DEPARTURE_UEC_PAGE = 2; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_WORK_DURATION_UEC_PAGE = 3; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_WORK_ARRIVAL_UEC_PAGE = 4; + + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_SCHOOL_MODEL_UEC_PAGE = 5; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_SCHOOL_DEPARTURE_UEC_PAGE = 6; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_SCHOOL_DURATION_UEC_PAGE = 7; + public static final int MANDATORY_TOUR_DEP_TIME_AND_DUR_SCHOOL_ARRIVAL_UEC_PAGE = 8; + + public static final String PROPERTIES_SCHEDULING_NUMBER_OF_TIME_PERIODS = "Scheduling.NumberOfTimePeriods"; + public static final String PROPERTIES_SCHEDULING_FIRST_TIME_PERIOD = "Scheduling.FirstTimePeriod"; + + static final String PROPERTIES_RESTART_WITH_HOUSEHOLD_SERVER = "RunModel.RestartWithHhServer"; + static final String PROPERTIES_REREAD_MATRIX_DATA_ON_RESTART = "RunModel.RereadMatrixDataOnRestart"; + + public static final String PROPERTIES_RESULTS_AUTO_OWNERSHIP = "Results.AutoOwnership"; + public static final String PROPERTIES_RESULTS_CDAP = "Results.CoordinatedDailyActivityPattern"; + + public static final String PROPERTIES_WRITE_DATA_TO_FILE = "Results.WriteDataToFiles"; + public static final String PROPERTIES_WRITE_DATA_TO_DATABASE = "Results.WriteDataToDatabase"; + public static final String PROPERTIES_WRITE_TRIP_MATRICES = "Results.WriteTripMatrices"; + + public static final String PROPERTIES_SAVE_TOUR_MODE_CHOICE_UTILS = "TourModeChoice.Save.UtilsAndProbs"; + + public static final String PROPERTIES_WORK_SCHOOL_LOCATION_CHOICE_SHADOW_PRICE_INPUT_FILE = "UsualWorkAndSchoolLocationChoice.ShadowPrice.Input.File"; + + public static final String PROPERTIES_NUMBER_OF_GLOBAL_ITERATIONS = "Global.iterations"; + + public static final String ALT_FIELD_NAME = "a"; + public static final String START_FIELD_NAME = "depart"; + public static final String END_FIELD_NAME = "arrive"; + + + private static final int NUM_WRITE_PACKETS = 2000; + + + + private boolean restartFromDiskObjectFile = false; + + private ResourceBundle resourceBundle; + + private MatrixDataServerIf ms; + + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + protected String projectDirectory; + protected String hhDiskObjectFile; + protected String hhDiskObjectKey; + protected String tazDiskObjectFile; + protected String tazDiskObjectKey; + + private HashMap> cdapByHhSizeAndPattern; + private HashMap> cdapByPersonTypeAndActivity; + + + + + + public CtrampApplication( ResourceBundle rb ){ + resourceBundle = rb; + projectDirectory = ResourceUtil.getProperty(resourceBundle, PROPERTIES_PROJECT_DIRECTORY); + } + + + + public void setupModels( ModelStructure modelStructure, TazDataIf tazDataManager ){ + + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + } + + + public void runPopulationSynthesizer( PopulationSynthesizer populationSynthesizer ){ + + // run population synthesizer + boolean runModelPopulationSynthesizer = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_POPSYN); + if(runModelPopulationSynthesizer){ + populationSynthesizer.runPopulationSynthesizer(); + } + + } + + //run models without a trip matrix writer + public void runModels( HouseholdDataManagerIf householdDataManager, CtrampDmuFactoryIf dmuFactory, int globalIterationNumber) { + runModels(householdDataManager, dmuFactory, globalIterationNumber, null); + } + + public void runModels( HouseholdDataManagerIf householdDataManager, CtrampDmuFactoryIf dmuFactory, int globalIterationNumber, TripMatrixWriterIf tripMatrixWriter ){ + + logger.info("Running JPPF based CtrampApplication.runModels() with " + householdDataManager.getNumHouseholds() + " households."); + + String matrixServerAddress = ""; + int serverPort = 0; + try { + // get matrix server address. if "none" is specified, no server will be started, and matrix io will ocurr within the current process. + matrixServerAddress = resourceBundle.getString( "RunModel.MatrixServerAddress" ); + try { + // get matrix server port. + serverPort = Integer.parseInt( resourceBundle.getString( "RunModel.MatrixServerPort" ) ); + } + catch ( MissingResourceException e ) { + // if no matrix server address entry is found, leave undefined -- it's eithe not needed or show could create an error. + } + } + catch ( MissingResourceException e ) { + // if no matrix server address entry is found, set to localhost, and a separate matrix io process will be started on localhost. + matrixServerAddress = "localhost"; + serverPort = MATRIX_DATA_SERVER_PORT; + } + + + MatrixDataServer matrixServer = null; + + try { + + if ( ! matrixServerAddress.equalsIgnoreCase("none") ) { + + if ( matrixServerAddress.equalsIgnoreCase("localhost") ) { + matrixServer = startMatrixServerProcess( matrixServerAddress, serverPort ); + ms = matrixServer; + } + else { + MatrixDataServerRmi mds = new MatrixDataServerRmi( matrixServerAddress, serverPort, MatrixDataServer.MATRIX_DATA_SERVER_NAME ); + ms = mds; + + boolean rereadMatrixDataOnRestart = ResourceUtil.getBooleanProperty( resourceBundle, PROPERTIES_REREAD_MATRIX_DATA_ON_RESTART, true); + if (rereadMatrixDataOnRestart) ms.clear(); + ms.start32BitMatrixIoServer( MatrixType.TPPLUS ); + + MatrixDataManager mdm = MatrixDataManager.getInstance(); + mdm.setMatrixDataServerObject( ms ); + + } + + } + + + } + catch ( Exception e ) { + + if ( matrixServerAddress.equalsIgnoreCase("localhost") ) { + matrixServer.stop32BitMatrixIoServer(); + } + logger.error ( String.format( "exception caught running ctramp model components -- exiting." ), e ); + throw new RuntimeException(); + + } + + + + + // run core activity based model for the specified iteration + runIteration( globalIterationNumber, householdDataManager, dmuFactory, tripMatrixWriter); + + + + // if a separate process for running matrix data mnager was started, we're done with it, so close it. + if ( matrixServerAddress.equalsIgnoreCase("localhost") ) { + matrixServer.stop32BitMatrixIoServer(); + } + else { + if ( ! matrixServerAddress.equalsIgnoreCase("none") ) + ms.stop32BitMatrixIoServer(); + } + + } + + + + private void runIteration( int iteration, HouseholdDataManagerIf householdDataManager, CtrampDmuFactoryIf dmuFactory, TripMatrixWriterIf tripMatrixWriter) { + + String restartModel = ""; + if ( hhDiskObjectKey != null && ! hhDiskObjectKey.equalsIgnoreCase("none") ) { + /* + String doFileName = hhDiskObjectFile + "_" + hhDiskObjectKey; + householdDataManager.createHhArrayFromSerializedObjectInFile( doFileName, hhDiskObjectKey ); + restartModel = hhDiskObjectKey; + restartModels ( householdDataManager ); + */ + } + else { + restartModel = ResourceUtil.getProperty( resourceBundle, PROPERTIES_RESTART_WITH_HOUSEHOLD_SERVER ); + if ( restartModel == null ) + restartModel = "none"; + if ( ! restartModel.equalsIgnoreCase("none") ) + restartModels ( householdDataManager ); + } + + + + JPPFClient jppfClient = new JPPFClient(); + + boolean runUsualWorkSchoolChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_WORKSCHOOL_CHOICE); + if(runUsualWorkSchoolChoiceModel){ + + // create an object for calculating destination choice attraction size terms and managing shadow price calculations. + DestChoiceSize dcSizeObj = new DestChoiceSize( modelStructure, tazDataManager ); + + // new the usual school and location choice model object + UsualWorkSchoolLocationChoiceModel usualWorkSchoolLocationChoiceModel = new UsualWorkSchoolLocationChoiceModel(resourceBundle, restartModel, jppfClient, modelStructure, ms, tazDataManager, dcSizeObj, dmuFactory ); + + // run the model + logger.info ( "starting usual work and school location choice."); + usualWorkSchoolLocationChoiceModel.runSchoolAndLocationChoiceModel(householdDataManager); + logger.info ( "finished with usual work and school location choice."); + + logger.info ( "writing work/school location choice results file; may take a few minutes ..." ); + usualWorkSchoolLocationChoiceModel.saveResults( householdDataManager, projectDirectory, iteration ); + logger.info ( String.format("finished writing results file.") ); + + usualWorkSchoolLocationChoiceModel = null; + dcSizeObj = null; + + } + + + + boolean runAutoOwnershipChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AUTO_OWNERSHIP ); + boolean runFreeParkingChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_FREE_PARKING_AVAILABLE ); + boolean runCoordinatedDailyActivityPatternChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_DAILY_ACTIVITY_PATTERN ); + boolean runMandatoryTourFreqChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_MANDATORY_TOUR_FREQ ); + boolean runMandatoryTourTimeOfDayChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_MAND_TOUR_DEP_TIME_AND_DUR ); + boolean runMandatoryTourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_MAND_TOUR_MODE_CHOICE ); + boolean runJointTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_FREQ ); + boolean runJointTourLocationChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_LOCATION_CHOICE ); + boolean runJointTourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_MODE_CHOICE ); + boolean runJointTourDepartureTimeAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_DEP_TIME_AND_DUR ); + boolean runIndivNonManTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_FREQ ); + boolean runIndivNonManTourLocationChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_LOCATION_CHOICE ); + boolean runIndivNonManTourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_MODE_CHOICE ); + boolean runIndivNonManTourDepartureTimeAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_DEP_TIME_AND_DUR ); + boolean runAtWorkSubTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_FREQ ); + boolean runAtWorkSubtourLocationChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_LOCATION_CHOICE ); + boolean runAtWorkSubtourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_MODE_CHOICE ); + boolean runAtWorkSubtourDepartureTimeAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_DEP_TIME_AND_DUR ); + boolean runStopFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_STOP_FREQUENCY ); + boolean runStopLocationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_STOP_LOCATION ); + + + boolean runHouseholdModels = false; + if ( + runAutoOwnershipChoiceModel + || runFreeParkingChoiceModel + || runCoordinatedDailyActivityPatternChoiceModel + || runMandatoryTourFreqChoiceModel + || runMandatoryTourModeChoiceModel + || runMandatoryTourTimeOfDayChoiceModel + || runJointTourFrequencyModel + || runJointTourLocationChoiceModel + || runJointTourModeChoiceModel + || runJointTourDepartureTimeAndDurationModel + || runIndivNonManTourFrequencyModel + || runIndivNonManTourLocationChoiceModel + || runIndivNonManTourModeChoiceModel + || runIndivNonManTourDepartureTimeAndDurationModel + || runAtWorkSubTourFrequencyModel + || runAtWorkSubtourLocationChoiceModel + || runAtWorkSubtourModeChoiceModel + || runAtWorkSubtourDepartureTimeAndDurationModel + || runStopFrequencyModel + || runStopLocationModel + ) + runHouseholdModels = true; + + + + // disk object file is labeled with the next component eligible to be run if model restarted + String lastComponent = "uwsl"; + String nextComponent = "ao"; + + if( runHouseholdModels ) { + + logger.info ( "starting HouseholdChoiceModelRunner." ); + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + HouseholdChoiceModelRunner runner = new HouseholdChoiceModelRunner( propertyMap, jppfClient, restartModel, householdDataManager, ms, modelStructure, tazDataManager, dmuFactory ); + runner.runHouseholdChoiceModels(); + + if( runAutoOwnershipChoiceModel ){ + saveAoResults( householdDataManager, projectDirectory ); + logAoResults( householdDataManager ); + lastComponent = "ao"; + nextComponent = "fp"; + } + + if( runFreeParkingChoiceModel ){ + logFpResults( householdDataManager ); + lastComponent = "fp"; + nextComponent = "cdap"; + } + + if( runCoordinatedDailyActivityPatternChoiceModel ){ + saveCdapResults( householdDataManager, projectDirectory ); + logCdapResults( householdDataManager ); + lastComponent = "cdap"; + nextComponent = "imtf"; + } + + if( runMandatoryTourFreqChoiceModel ){ + logImtfResults( householdDataManager ); + lastComponent = "imtf"; + nextComponent = "imtod"; + } + + if( runMandatoryTourTimeOfDayChoiceModel || runMandatoryTourModeChoiceModel ){ + lastComponent = "imtod"; + nextComponent = "jtf"; + } + + if( runJointTourFrequencyModel ){ + logJointModelResults( householdDataManager ); + lastComponent = "jtf"; + nextComponent = "jtl"; + } + + if( runJointTourLocationChoiceModel ){ + lastComponent = "jtl"; + nextComponent = "jtod"; + } + + if( runJointTourDepartureTimeAndDurationModel || runJointTourModeChoiceModel ){ + lastComponent = "jtod"; + nextComponent = "inmtf"; + } + + if( runIndivNonManTourFrequencyModel ){ + lastComponent = "inmtf"; + nextComponent = "inmtl"; + } + + if( runIndivNonManTourLocationChoiceModel ){ + lastComponent = "inmtl"; + nextComponent = "inmtod"; + } + + if( runIndivNonManTourDepartureTimeAndDurationModel || runIndivNonManTourModeChoiceModel ){ + lastComponent = "inmtod"; + nextComponent = "awf"; + } + + if( runAtWorkSubTourFrequencyModel ){ + logAtWorkSubtourFreqResults( householdDataManager ); + lastComponent = "awf"; + nextComponent = "awl"; + } + + if( runAtWorkSubtourLocationChoiceModel ){ + lastComponent = "awl"; + nextComponent = "awtod"; + } + + if( runAtWorkSubtourDepartureTimeAndDurationModel || runAtWorkSubtourModeChoiceModel ){ + lastComponent = "awtod"; + nextComponent = "stf"; + } + + if( runStopFrequencyModel ){ + logStfResults( householdDataManager, true); //individual + //logStfResults( householdDataManager, false ); //joint + lastComponent = "stf"; + nextComponent = "stl"; + } + + if( runStopLocationModel ){ + lastComponent = "stl"; + nextComponent = "done"; + } + + + + // write a disk object fle for the householdDataManager, in case we want to restart from the next step. + if ( hhDiskObjectFile != null && ! lastComponent.equalsIgnoreCase("uwsl") ) { + /* + logger.info ( String.format("writing household disk object file after %s choice model; may take a long time ...", lastComponent) ); + String hhFileName = hhDiskObjectFile + "_" + nextComponent; + householdDataManager.createSerializedHhArrayInFileFromObject( hhFileName, nextComponent ); + logger.info ( String.format("finished writing household disk object file = %s.", hhFileName) ); + */ + } + + logger.info ( "finished with HouseholdChoiceModelRunner." ); + + } + + + + + + boolean writeTextFileFlag = false; + boolean writeSqliteFlag = false; + boolean writeTripMatricesFlag = false; + try { + writeTextFileFlag = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_WRITE_DATA_TO_FILE); + } + catch ( MissingResourceException e ) { + // if exception is caught while getting property file value, then boolean flag remains false + } + try { + writeSqliteFlag = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_WRITE_DATA_TO_DATABASE); + } + catch ( MissingResourceException e ) { + // if exception is caught while getting property file value, then boolean flag remains false + } + try { + writeTripMatricesFlag = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_WRITE_TRIP_MATRICES); + } + catch ( MissingResourceException e ) { + // if exception is caught while getting property file value, then boolean flag remains false + } + + //write output text files and/or SQLite database + HouseholdDataWriter dataWriter = null; + if ( writeTextFileFlag || writeSqliteFlag ) { + dataWriter = new HouseholdDataWriter( resourceBundle, modelStructure, tazDataManager, dmuFactory, iteration ); + + if ( writeTextFileFlag ) + dataWriter.writeDataToFiles(householdDataManager); + + if ( writeSqliteFlag ) { + String dbFilename = ""; + try { + String baseDir = resourceBundle.getString(PROPERTIES_PROJECT_DIRECTORY); + dbFilename = baseDir + resourceBundle.getString(SQLITE_DATABASE_FILENAME) + "_" + iteration; + dataWriter.writeDataToDatabase(householdDataManager, dbFilename); + } + catch ( MissingResourceException e ) { + // if exception is caught while getting property file value, then boolean flag remains false + } + } + } + + //write trip matrices + if(writeTripMatricesFlag) { + tripMatrixWriter.writeMatrices(); + } + + } + + + + + public String getProjectDirectoryName() { + return projectDirectory; + } + + + private MatrixDataServer startMatrixServerProcess( String serverAddress, int serverPort ) { + + String className = MatrixDataServer.MATRIX_DATA_SERVER_NAME; + + MatrixDataServer matrixServer = new MatrixDataServer(); + + try { + + // create the concrete data server object + matrixServer.start32BitMatrixIoServer( MatrixType.TPPLUS ); + + } + catch ( RuntimeException e ) { + matrixServer.stop32BitMatrixIoServer(); + logger.error ( "RuntimeException caught in com.pb.models.ctramp.MatrixDataServer.main() -- exiting.", e ); + } + + // bind this concrete object with the cajo library objects for managing RMI + try { + Remote.config( serverAddress, serverPort, null, 0 ); + } + catch ( UnknownHostException e ) { + logger.error ( String.format( "UnknownHostException. serverAddress = %s, serverPort = %d -- exiting.", serverAddress, serverPort ), e ); + matrixServer.stop32BitMatrixIoServer(); + throw new RuntimeException(); + } + + try { + ItemServer.bind( matrixServer, className ); + } + catch ( RemoteException e ) { + logger.error ( String.format( "RemoteException. serverAddress = %s, serverPort = %d -- exiting.", serverAddress, serverPort ), e ); + matrixServer.stop32BitMatrixIoServer(); + throw new RuntimeException(); + } + + return matrixServer; + + } + + + public boolean restartFromDiskObjectFile() { + return restartFromDiskObjectFile; + } + + + public void restartModels ( HouseholdDataManagerIf householdDataManager ) { + + // if no filename was specified for the previous shadow price info, restartIter == -1. + // also, random counts will be reset to 1. + int restartIter = -1; + String fileName = ResourceUtil.getProperty( resourceBundle, PROPERTIES_WORK_SCHOOL_LOCATION_CHOICE_SHADOW_PRICE_INPUT_FILE ); + if ( fileName != null ) { + fileName = projectDirectory + fileName; + int underScoreIndex = fileName.lastIndexOf('_'); + int dotIndex = fileName.lastIndexOf('.'); + restartIter = Integer.parseInt( fileName.substring( underScoreIndex+1, dotIndex ) ); + } + + boolean runUsualWorkSchoolChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_WORKSCHOOL_CHOICE); + if ( runUsualWorkSchoolChoiceModel ) { + // the input file name should have indicated the iteration number prior to the iteration number desired to run. + // e.g. if the filename contains "..._4.csv", then the model should restart with uwsl iteration 5, using the random + // number count set at the end of iteration 4, stored in the HashMap with key of 4. + householdDataManager.resetUwslRandom( restartIter ); + } + else { + boolean runAutoOwnershipModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AUTO_OWNERSHIP); + if ( runAutoOwnershipModel ) { + // if restarting with ao, meaning not running uwsl, the shadow price input file should also be set to indicate + // the last shadow price iteration number from which the random number count should be taked to reset the ao count. + // e.g. if the filename contains "..._5.csv", then the model should reset the ar random count to that following uwsl iteration 5 + householdDataManager.resetAoRandom( restartIter ); + } + else { + boolean runFreeParkingAvailableModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_FREE_PARKING_AVAILABLE); + if ( runFreeParkingAvailableModel ) { + householdDataManager.resetFpRandom(); + } + else { + boolean runCoordinatedDailyActivityPatternModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_DAILY_ACTIVITY_PATTERN); + if ( runCoordinatedDailyActivityPatternModel ) { + householdDataManager.resetCdapRandom(); + } + else { + boolean runIndividualMandatoryTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_MANDATORY_TOUR_FREQ); + if ( runIndividualMandatoryTourFrequencyModel ) { + householdDataManager.resetImtfRandom(); + } + else { + boolean runIndividualMandatoryTourDepartureAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_MAND_TOUR_DEP_TIME_AND_DUR); + if ( runIndividualMandatoryTourDepartureAndDurationModel ) { + householdDataManager.resetImtodRandom(); + } + + else { + boolean runIndividualMandatoryTourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_MAND_TOUR_MODE_CHOICE); + if ( runIndividualMandatoryTourModeChoiceModel ) { + householdDataManager.resetImmcRandom(); + } + else { + boolean runJointTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_FREQ); + if ( runJointTourFrequencyModel ) { + householdDataManager.resetJtfRandom(); + } + else { + boolean runJointTourLocationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_LOCATION_CHOICE); + if ( runJointTourLocationModel ) { + householdDataManager.resetJtlRandom(); + } + else { + boolean runJointTourDepartureAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_DEP_TIME_AND_DUR); + if ( runJointTourDepartureAndDurationModel ) { + householdDataManager.resetJtodRandom(); + } + else { + boolean runJointTourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_JOINT_TOUR_MODE_CHOICE); + if ( runJointTourModeChoiceModel ) { + householdDataManager.resetJmcRandom(); + } + else { + boolean runIndividualNonMandatoryTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_FREQ); + if ( runIndividualNonMandatoryTourFrequencyModel ) { + householdDataManager.resetInmtfRandom(); + } + else { + boolean runIndividualNonMandatoryTourLocationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_LOCATION_CHOICE); + if ( runIndividualNonMandatoryTourLocationModel ) { + householdDataManager.resetInmtlRandom(); + } + else { + boolean runIndividualNonMandatoryTourDepartureAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_DEP_TIME_AND_DUR); + if ( runIndividualNonMandatoryTourDepartureAndDurationModel ) { + householdDataManager.resetInmtodRandom(); + } + + else { + boolean runIndividualNonMandatoryModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_MODE_CHOICE); + if ( runIndividualNonMandatoryModeChoiceModel ) { + householdDataManager.resetInmmcRandom(); + } + else { + boolean runAtWorkSubTourFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_FREQ); + if ( runAtWorkSubTourFrequencyModel ) { + householdDataManager.resetAwfRandom(); + } + else { + boolean runAtWorkSubtourLocationChoiceModel = ResourceUtil.getBooleanProperty( resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_LOCATION_CHOICE ); + if ( runAtWorkSubtourLocationChoiceModel ) { + householdDataManager.resetAwlRandom(); + } + else { + boolean runAtWorkSubtourDepartureTimeAndDurationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_DEP_TIME_AND_DUR); + if ( runAtWorkSubtourDepartureTimeAndDurationModel ) { + householdDataManager.resetAwtodRandom(); + } + else { + boolean runAtWorkSubtourModeChoiceModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_AT_WORK_SUBTOUR_MODE_CHOICE); + if ( runAtWorkSubtourModeChoiceModel ) { + householdDataManager.resetAwmcRandom(); + } + else { + boolean runStopFrequencyModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_STOP_FREQUENCY); + if ( runStopFrequencyModel ) { + householdDataManager.resetStfRandom(); + } + else { + boolean runStopLocationModel = ResourceUtil.getBooleanProperty(resourceBundle, PROPERTIES_RUN_STOP_LOCATION); + if ( runStopLocationModel ) { + householdDataManager.resetStlRandom(); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + + + /** + * Loops through the households in the HouseholdDataManager, gets the auto ownership + * result for each household, and writes a text file with hhid and auto ownership. + * + * @param householdDataManager is the object from which the array of household objects can be retrieved. + * @param projectDirectory is the root directory for the output file named + */ + private void saveAoResults(HouseholdDataManagerIf householdDataManager, String projectDirectory){ + + String aoResultsFileName; + try { + aoResultsFileName = resourceBundle.getString( PROPERTIES_RESULTS_AUTO_OWNERSHIP ); + } + catch ( MissingResourceException e ) { + // if filename not specified in properties file, don't need to write it. + return; + } + + + FileWriter writer; + PrintWriter outStream = null; + if ( aoResultsFileName != null ) { + + aoResultsFileName = projectDirectory + aoResultsFileName; + + try { + writer = new FileWriter(new File(aoResultsFileName)); + outStream = new PrintWriter (new BufferedWriter( writer ) ); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred opening AO results file: %s.", aoResultsFileName ) ); + throw new RuntimeException(e); + } + + + outStream.println ( "HHID,AO" ); + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + int hhid = household.getHhId(); + int ao = household.getAutoOwnershipModelResult(); + + outStream.println( String.format( "%d,%d", hhid, ao ) ); + + } + + } + + outStream.close(); + + } + + } + + + private void logAoResults( HouseholdDataManagerIf householdDataManager ){ + + String[] aoCategoryLabel = { "0 autos", "1 auto", "2 autos", "3 autos", "4 or more autos" }; + + logger.info( "" ); + logger.info( "" ); + logger.info( "Auto Ownership Model Results" ); + logger.info( String.format("%-16s %10s", "Category", "Num HHs" )); + + + + // track the results + int[] hhsByAutoOwnership; + hhsByAutoOwnership = new int[aoCategoryLabel.length]; + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + int ao = household.getAutoOwnershipModelResult(); + + if ( ao >= aoCategoryLabel.length ) + ao = aoCategoryLabel.length - 1; + + hhsByAutoOwnership[ao]++; + + } + + + } + + + int total = 0; + for (int i=0; i < hhsByAutoOwnership.length; i++) { + logger.info( String.format("%-16s %10d", aoCategoryLabel[i], hhsByAutoOwnership[i] )); + total += hhsByAutoOwnership[i]; + } + logger.info( String.format("%-16s %10d", "Total", total )); + + } + + + private void logFpResults( HouseholdDataManagerIf householdDataManager ){ + + String[] fpCategoryLabel = { "Free Available", "Must Pay" }; + + logger.info( "" ); + logger.info( "" ); + logger.info( "Free Parking Model Results" ); + logger.info( String.format("%-16s %10s", "Category", "Num Persons" )); + + + + // track the results + int[] personsByFreeParking; + personsByFreeParking = new int[fpCategoryLabel.length]; + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + // note that person is a 1-based array + HouseholdIf household = householdArray[i]; + PersonIf[] person = household.getPersons(); + for (int j=1; j= 0 ) { + personsByFreeParking[fp]++; + } + else { + logger.error( "invalid result = " + fp + " for personid = " + person[j].getPersonId() ); + throw new RuntimeException(); + } + + } + } + + + } + + + int total = 0; + for (int i=0; i < personsByFreeParking.length; i++) { + logger.info( String.format("%-16s %10d", fpCategoryLabel[i], personsByFreeParking[i] )); + total += personsByFreeParking[i]; + } + logger.info( String.format("%-16s %10d", "Total", total )); + + } + + + /** + * Records the coordinated daily activity pattern model results to the logger. A household-level + * summary simply records each pattern type and a person-level summary summarizes the activity + * choice by person type (full-time worker, university student, etc). + * + */ + public void logCdapResults( HouseholdDataManagerIf householdDataManager ){ + + String[] activityNameArray = { Definitions.MANDATORY_PATTERN, Definitions.NONMANDATORY_PATTERN, Definitions.HOME_PATTERN }; + + getLogReportSummaries( householdDataManager ); + + + + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info("Coordinated Daily Activity Pattern Model Results"); + + // count of activities by person type + logger.info(" "); + logger.info("CDAP Results: Count of activities by person type"); + String firstHeader = "Person type "; + String secondHeader = "----------------------------- "; + for(int i=0;i hhSizeKeySet = cdapByHhSizeAndPattern.keySet(); + Integer[] hhSizeKeyArray = new Integer[hhSizeKeySet.size()]; + hhSizeKeySet.toArray(hhSizeKeyArray); + Arrays.sort(hhSizeKeyArray); + + int total = 0; + for(int i=0;i patternMap = cdapByHhSizeAndPattern.get(hhSizeKeyArray[i]); + Set patternKeySet = patternMap.keySet(); + String[] patternKeyArray = new String[patternKeySet.size()]; + patternKeySet.toArray(patternKeyArray); + Arrays.sort(patternKeyArray); + for(int j=0;j countByPersonType = new HashMap(); + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + PersonIf[] personArray = householdArray[i].getPersons(); + for(int j=1; j < personArray.length; j++){ + + // only summarize persons with mandatory pattern + String personActivity = personArray[j].getCdapActivity(); + if ( personActivity != null && personArray[j].getCdapActivity().equalsIgnoreCase("M") ) { + + String personTypeString = personArray[j].getPersonType(); + int choice = personArray[j].getImtfChoice(); + + // count the results + if(countByPersonType.containsKey(personTypeString)){ + + int[] counterArray = countByPersonType.get(personTypeString); + counterArray[choice-1]++; + countByPersonType.put(personTypeString, counterArray); + + } + else{ + + int[] counterArray = new int[choiceResults.length]; + counterArray[choice-1]++; + countByPersonType.put(personTypeString, counterArray); + + } + } + + } + + } + + + } + + + + for(int i=0;i partySizeFreq = new TreeMap(); + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + TourIf[] jt = householdArray[i].getJointTourArray(); + int jtfAlt = householdArray[i].getJointTourFreqChosenAlt(); + + if ( jt == null ) { + + int index = 0; + if ( jtfAlt > 1 ) { + logger.error ( String.format( "HHID=%d, joint tour array is null, but a valid alternative=%d is recorded for the household.", householdArray[i].getHhId(), jtfAlt ) ); + throw new RuntimeException(); + } + else if ( jtfAlt == 1 ) { + index = indexOffset + jtfAlt; + } + else { + index = -jtfAlt; + } + + jointTourChoiceFreq[index]++; + } + else { + + + if ( jtfAlt <= 1 ) { + logger.error ( String.format( "HHID=%d, joint tour array is not null, but an invalid alternative=%d is recorded for the household.", householdArray[i].getHhId(), jtfAlt ) ); + throw new RuntimeException(); + } + + int index = indexOffset + jtfAlt; + jointTourChoiceFreq[index]++; + + + // determine party size frequency for joint tours generated + PersonIf[] persons = householdArray[i].getPersons(); + for ( int j=0; j < jt.length; j++ ) { + + int compAlt = jt[j].getJointTourComposition(); + + // determine number of children and adults in tour + int adults = 0; + int children = 0; + byte[] participants = jt[j].getPersonNumArray(); + for ( int k=0; k < participants.length; k++ ) { + index = participants[k]; + PersonIf person = persons[index]; + if ( person.getPersonIsAdult() == 1 ) + adults++; + else + children++; + } + + // create a key to use for a frequency map for "JointTourPurpose_Composition_NumAdults_NumChildren" + String key = String.format( "%s_%d_%d_%d", jt[j].getTourPrimaryPurpose(), compAlt, adults, children ); + + int value = 0; + if ( partySizeFreq.containsKey( key ) ) + value = partySizeFreq.get( key ); + partySizeFreq.put( key, ++value ); + + } + + } + + } + + } + + + + + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info("Joint Tour Frequency and Joint Tour Composition Model Results"); + + + logger.info(" "); + logger.info( "Frequency Table of Households by Joint Tour Frequency Choice" ); + logger.info ( String.format( "%-5s %-26s %12s", "Alt", "Alt Name", "Households" ) ); + + + // treat the first few rows of the table differently - no joint tours chosen and therefore no composition chosen. + // so we just want to print the total households chhosing no joint tours in the "total" column. + // later we'll add this total to the tanle total in the last row. + logger.info ( String.format( "%-5s %-26s %12d", "-", "single person hh", jointTourChoiceFreq[2] ) ); + logger.info ( String.format( "%-5s %-26s %12d", "-", "less than 2 persons travel", jointTourChoiceFreq[3] ) ); + logger.info ( String.format( "%-5s %-26s %12d", "-", "only pre-schoolers travel", jointTourChoiceFreq[4] ) ); + + + int rowTotal = jointTourChoiceFreq[2] + jointTourChoiceFreq[3] + jointTourChoiceFreq[4]; + for ( int i=1; i < altLabels.length; i++ ) { + int index = indexOffset + i; + logger.info ( String.format( "%-5d %-26s %12d", i, altLabels[i], jointTourChoiceFreq[index] ) ); + rowTotal += jointTourChoiceFreq[index]; + } + logger.info ( String.format( "%-34s %12d", "Total Households", rowTotal ) ); + + + logger.info(" "); + logger.info(" "); + logger.info(" "); + + logger.info( "Frequency Table of Joint Tours by All Parties Generated" ); + logger.info ( String.format( "%-5s %-10s %-10s %10s %10s %10s", "N", "Purpose", "Type", "Adults", "Children", "Freq" ) ); + + + int count = 1; + for ( String key : partySizeFreq.keySet() ) { + + int start = 0; + int end = 0; + int compIndex = 0; + int adults = 0; + int children = 0; + String indexString = ""; + String purpose = ""; + + start = 0; + end = key.indexOf( '_', start ); + purpose = key.substring( start, end ); + + start = end+1; + end = key.indexOf( '_', start ); + indexString = key.substring( start, end ); + compIndex = Integer.parseInt ( indexString ); + + start = end+1; + end = key.indexOf( '_', start ); + indexString = key.substring( start, end ); + adults = Integer.parseInt ( indexString ); + + start = end+1; + indexString = key.substring( start ); + children = Integer.parseInt ( indexString ); + + logger.info ( String.format( "%-5d %-10s %-10s %10d %10d %10d", count++, purpose, JointTourModels.JOINT_TOUR_COMPOSITION_NAMES[compIndex], adults, children, partySizeFreq.get(key) ) ); + } + + + logger.info(" "); + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info(" "); + + } + + /** + * Logs the results of the individual/joint tour stop frequency model. + * + */ + public void logStfResults( HouseholdDataManagerIf householdDataManager, Boolean isIndividual){ + + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info((isIndividual ? "Individual" : "Joint") + " Tour Stop Frequency Model Results"); + + // count of model results + logger.info(" "); + String firstHeader = "Tour Purpose "; + String secondHeader = "--------------- "; + + int[] obStopsAlt = StopFrequencyDMU.NUM_OB_STOPS_FOR_ALT; + int[] ibStopsAlt = StopFrequencyDMU.NUM_IB_STOPS_FOR_ALT; + + //hash to accumulate results + HashMap chosen = new HashMap(); + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + if(isIndividual) { + + //individual tours + PersonIf[] personArray = householdArray[i].getPersons(); + for(int j=1; j < personArray.length; j++){ + + List tourList = new ArrayList(); + + // apply stop frequency for all person tours + tourList.addAll( personArray[j].getListOfWorkTours() ); + tourList.addAll( personArray[j].getListOfSchoolTours() ); + tourList.addAll( personArray[j].getListOfIndividualNonMandatoryTours() ); + tourList.addAll( personArray[j].getListOfAtWorkSubtours() ); + + for ( TourIf t : tourList ) { + + String purpose = t.getTourPurpose().toLowerCase(); + int choice = t.getStopFreqChoice(); + + if(chosen.containsKey(purpose)) { + int[] countArray = chosen.get(purpose); + countArray[choice] = countArray[choice] + 1; + chosen.put(purpose, countArray); + + } else { + int[] countArray = new int[obStopsAlt.length]; + countArray[choice] = countArray[choice] + 1; + chosen.put(purpose, countArray); + } + } + + } + + } else { + + //joint tours + TourIf[] jointTourArray = householdArray[i].getJointTourArray(); + if (jointTourArray!=null) { + for (int j=0; j>(); + cdapByPersonTypeAndActivity = new HashMap>(); + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + // get the array of households + HouseholdIf[] partialHhArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for ( HouseholdIf hhObject : partialHhArray ) { + + // get the household's activity pattern choice + String pattern = hhObject.getCoordinatedDailyActivityPattern(); + + PersonIf[] personArray = hhObject.getPersons(); + for( int j=1; j < personArray.length; j++ ) { + + // get person's activity string + String activityString = personArray[j].getCdapActivity(); + + // get the person type to simmarize results by + String personTypeString = personArray[j].getPersonType(); + + // check if the person type is in the map + if( cdapByPersonTypeAndActivity.containsKey( personTypeString )){ + + HashMap activityCountMap = cdapByPersonTypeAndActivity.get( personTypeString ); + + // check if the activity is in the activity map + int currentCount = 1; + if( activityCountMap.containsKey(activityString) ) + currentCount = activityCountMap.get(activityString) + 1; + + activityCountMap.put(activityString, currentCount); + cdapByPersonTypeAndActivity.put(personTypeString, activityCountMap); + + + } + else{ + + HashMap activityCountMap = new HashMap(); + activityCountMap.put(activityString, 1); + cdapByPersonTypeAndActivity.put(personTypeString, activityCountMap); + + } // is personType in map if + + } // j (person loop) + + + // count each type of pattern string by hhSize + if( cdapByHhSizeAndPattern.containsKey(pattern.length()) ) { + + HashMap patternCountMap = cdapByHhSizeAndPattern.get( pattern.length() ); + + int currentCount = 1; + if( patternCountMap.containsKey(pattern) ) + currentCount = patternCountMap.get(pattern) + 1; + patternCountMap.put(pattern, currentCount); + cdapByHhSizeAndPattern.put(pattern.length(), patternCountMap); + + } + else { + + HashMap patternCountMap = new HashMap(); + patternCountMap.put(pattern, 1); + cdapByHhSizeAndPattern.put(pattern.length(), patternCountMap); + + } // is personType in map if + + } + + } + + } + + + /** + * Loops through the households in the HouseholdDataManager, gets the coordinated daily + * activity pattern for each person in the household, and writes a text file with hhid, + * personid, persnum, and activity pattern. + * + * @param householdDataManager + */ + public void saveCdapResults( HouseholdDataManagerIf householdDataManager, String projectDirectory ){ + + String cdapResultsFileName; + try { + cdapResultsFileName = resourceBundle.getString( PROPERTIES_RESULTS_CDAP ); + } + catch ( MissingResourceException e ) { + // if filename not specified in properties file, don't need to write it. + return; + } + + + FileWriter writer; + PrintWriter outStream = null; + if ( cdapResultsFileName != null ) { + + cdapResultsFileName = projectDirectory + cdapResultsFileName; + + try { + writer = new FileWriter(new File(cdapResultsFileName)); + outStream = new PrintWriter (new BufferedWriter( writer ) ); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred opening CDAP results file: %s.", cdapResultsFileName ) ); + throw new RuntimeException(e); + } + + + outStream.println( "HHID,PersonID,PersonNum,PersonType,ActivityString" ); + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + int hhid = household.getHhId(); + + // get the pattern for each person + PersonIf[] personArray = household.getPersons(); + for( int j=1; j < personArray.length; j++ ) { + + PersonIf person = personArray[j]; + + int persId = person.getPersonId(); + int persNum = person.getPersonNum(); + int persType = person.getPersonTypeNumber(); + String activityString = person.getCdapActivity(); + + outStream.println( String.format("%d,%d,%d,%d,%s", hhid, persId, persNum, persType, activityString )); + + } // j (person loop) + + } + + } + + outStream.close(); + + } + + } + + + + + /** + * Logs the results of the model. + * + */ + public void logAtWorkSubtourFreqResults( HouseholdDataManagerIf householdDataManager ){ + + String[] alternativeNames = modelStructure.getAwfAltLabels(); + HashMap awfByPersonType = new HashMap(); + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges( householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + for(int i=0; i < householdArray.length; ++i){ + + // get this household's person array + PersonIf[] personArray = householdArray[i].getPersons(); + + // loop through the person array (1-based) + for(int j=1;j tourList = person.getListOfWorkTours(); + if ( tourList == null || tourList.size() == 0 ) + continue; + + // count the results by person type + String personTypeString = person.getPersonType(); + + + for ( TourIf workTour : tourList ) { + + int choice = 0; + if ( person.getListOfAtWorkSubtours().size() == 0 ) + choice = 1; + else { + choice = workTour.getSubtourFreqChoice(); + if ( choice == 0 ) + choice++; + } + + + // count the results by person type + if( awfByPersonType.containsKey(personTypeString)){ + int[] counterArray = awfByPersonType.get(personTypeString); + counterArray[choice-1]++; + awfByPersonType.put( personTypeString, counterArray ); + + } + else{ + int[] counterArray = new int[alternativeNames.length]; + counterArray[choice-1]++; + awfByPersonType.put(personTypeString, counterArray); + } + + } + + + } + + } + + } + + + + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info("At-Work Subtour Frequency Model Results"); + + // count of model results + logger.info(" "); + String firstHeader = "Person type "; + String secondHeader = "--------------------------- "; + + + for(int i=0;i getWriteHouseholdRanges( int numberOfHouseholds ) { + + ArrayList startEndIndexList = new ArrayList(); + + int startIndex = 0; + int endIndex = 0; + + while ( endIndex < numberOfHouseholds - 1 ) { + endIndex = startIndex + NUM_WRITE_PACKETS - 1; + if ( endIndex + NUM_WRITE_PACKETS > numberOfHouseholds ) + endIndex = numberOfHouseholds - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += NUM_WRITE_PACKETS; + } + + + return startEndIndexList; + + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/DestChoiceModelManager.java b/src/java/com/pb/models/ctrampIf/jppf/DestChoiceModelManager.java new file mode 100644 index 0000000..5943ba1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/DestChoiceModelManager.java @@ -0,0 +1,214 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.MatrixDataManager; +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.common.calculator.TableDataSetManager; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.jppf.MandatoryDestChoiceModel; + +public class DestChoiceModelManager implements Serializable { + + private Logger logger = Logger.getLogger(DestChoiceModelManager.class); + + private static DestChoiceModelManager objInstance = null; + + private MatrixDataManager mdm = null; + private LinkedList modelQueue = null; + + private HashMap propertyMap; + private ModelStructure modelStructure; + private String tourCategory; + private TazDataIf tazDataManager; + private DestChoiceSize dcSizeObj; + private String dcUecFileName; + private String soaUecFileName; + private int soaSampleSize; + private String modeChoiceUecFileName; + private CtrampDmuFactoryIf dmuFactory; + + private int modelIndex; + private int currentIteration; + + private int completedHouseholds = 0; + + + + private DestChoiceModelManager(){ + } + + + + public static synchronized DestChoiceModelManager getInstance() { + if ( objInstance == null ) { + objInstance = new DestChoiceModelManager(); + objInstance.modelIndex = 0; + objInstance.currentIteration = 0; + objInstance.completedHouseholds = 0; + return objInstance; + } + else { + return objInstance; + } + } + + + + // the task instances should call needToInitialize() first, then this method if necessary. + public synchronized void factorySetup( HashMap propertyMap, MatrixDataServerIf ms, ModelStructure modelStructure, String tourCategory, TazDataIf tazDataManager, DestChoiceSize dcSizeObj, + String dcUecFileName, String soaUecFileName, int soaSampleSize, String modeChoiceUecFileName, CtrampDmuFactoryIf dmuFactory, String restartModelString ) { + + if ( modelQueue != null ) { + return; + } + + modelIndex = 0; + completedHouseholds = 0; + + System.out.println( String.format( "initializing DC ModelManager: thread=%s.", Thread.currentThread().getName() ) ); + + this.propertyMap = propertyMap; + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + this.tourCategory = tourCategory; + this.dcSizeObj = dcSizeObj; + this.dcUecFileName = dcUecFileName; + this.soaUecFileName = soaUecFileName; + this.soaSampleSize = soaSampleSize; + this.modeChoiceUecFileName = modeChoiceUecFileName; + this.dmuFactory = dmuFactory; + + + // the first thread to reach this method initializes the modelQueue used to recycle dcModel objects. + modelQueue = new LinkedList(); + + + + // Initialize the MatrixDataManager to use the MatrixDataServer instance passed in, unless ms is null. + if ( ms == null ) { + if ( mdm != null ) { + logger.info ( Thread.currentThread().getName() + ": No remote MatrixServer being used, but MatrixDataManager already exists - resetting for DestChoiceModelManager." ); + mdm.clearData(); + } + else { + logger.info ( Thread.currentThread().getName() + ": No remote MatrixServer being used, MatrixDataManager will get created when needed by DestChoiceModelManager." ); + } + } + else if ( mdm == null ) { + String testString = ms.testRemote(); + logger.info ( String.format( Thread.currentThread().getName() + ": DestChoiceModelManager needs MatrixDataManager, MatrixDataServer connection test: %s", testString ) ); + mdm = MatrixDataManager.getInstance(); + mdm.setMatrixDataServerObject( ms ); + } + else { + logger.info ( Thread.currentThread().getName() + ": MatrixDataManager already exists - resetting for DestChoiceModelManager." ); + mdm.clearData(); + } + + + TableDataSetManager tdm = TableDataSetManager.getInstance(); + tdm.clearData(); + } + + + public void returnDcModelObject ( MandatoryDestChoiceModel dcModel, int taskIndex, int startIndex, int endIndex ) { + modelQueue.add( dcModel ); + completedHouseholds += (endIndex - startIndex + 1); + int probCalcs = dcModel.getProbCalcs(); + logger.info( String.format( "returned dcModel=%d to queue, task=%d, thread=%s, completedHouseholds=%d, probCalcs=%d.", dcModel.getModelIndex(), taskIndex, Thread.currentThread().getName(), completedHouseholds, probCalcs ) ); + } + + + /** + * @return DestChoiceModel object created if less than the max number have been created, otherwise retrieved from the queue. + * + */ + //public MandatoryDestChoiceModel getDcModelObject( int taskIndex, int iteration ) { + public synchronized MandatoryDestChoiceModel getDcModelObject( int taskIndex, int iteration ) { + + String message = ""; + MandatoryDestChoiceModel dcModel = null; + + if ( modelQueue.isEmpty() ) { + + modelIndex ++; + dcModel = createDestChoiceModelObject( modelIndex, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, + dcUecFileName, soaUecFileName, soaSampleSize, modeChoiceUecFileName, dmuFactory ); + message = String.format( "created dcModel=%d, task=%d, thread=%s.", modelIndex, taskIndex, Thread.currentThread().getName() ); + + } + else { + + // the first task processed with an iteration parameter greater than the manager's current iteration count clears the dcModel cache and updates the iteration count. + if ( iteration > currentIteration ) { + currentIteration = iteration; + completedHouseholds = 0; + } + + dcModel = modelQueue.remove(); + + message = String.format( "removed dcModel=%d from queue, task=%d, thread=%s.", dcModel.getModelIndex(), taskIndex, Thread.currentThread().getName() ); + + } + + logger.info( message ); + return dcModel; + + } + + + + private MandatoryDestChoiceModel createDestChoiceModelObject ( int modelIndex, HashMap propertyMap, ModelStructure modelStructure, String tourCategory, TazDataIf tazDataManager, DestChoiceSize dcSizeObj, + String dcUecFileName, String soaUecFileName, int soaSampleSize, String modeChoiceUecFileName, CtrampDmuFactoryIf dmuFactory ) { + + // create a new dcModel instance to be shared among tasks running in this node + MandatoryDestChoiceModel dcModel = new MandatoryDestChoiceModel( modelIndex, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, + dcUecFileName, soaUecFileName, soaSampleSize, modeChoiceUecFileName, dmuFactory ); + + return dcModel; + } + + + + + public void clearDcModels() { + + if ( modelQueue == null ) { + return; + } + + Iterator it = modelQueue.iterator(); + while ( it.hasNext() ) { + MandatoryDestChoiceModel dcModel = it.next(); + if ( dcModel != null ) { + logger.info( "cleaned up dcModel " + dcModel.getModelIndex() + "." ); + dcModel = null; + } + } + + modelIndex = 0; + completedHouseholds = 0; + + modelQueue.clear(); + modelQueue = null; + + dcSizeObj = null; + } + + + + public MatrixDataManager getMatrixDataManager() { + return mdm; + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/DestinationSampleOfAlternativesModel.java b/src/java/com/pb/models/ctrampIf/jppf/DestinationSampleOfAlternativesModel.java new file mode 100644 index 0000000..71ecadd --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/DestinationSampleOfAlternativesModel.java @@ -0,0 +1,408 @@ +package com.pb.models.ctrampIf.jppf; + +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Random; + +import org.apache.log4j.Logger; + + +public class DestinationSampleOfAlternativesModel implements Serializable { + + private transient Logger logger = Logger.getLogger(DestinationSampleOfAlternativesModel.class); + + // set to false to store probabilities in cache for re-use; true to disable probabilities cache. + private static final boolean ALWAYS_COMPUTE_PROBABILITIES = false; + + private static final int DC_SOA_DATA_SHEET = 0; + private String dcSoaUecFileName; + private int sampleSize; + + + private int currentOrigTaz; + private double[][] probabilitiesCache; + private double[][] cumProbabilitiesCache; + private int currentWorkTaz; + private double[][] subtourProbabilitiesCache; + private double[][] subtourCumProbabilitiesCache; + + + // destsSample[] and destsAvailable[] are indexed by purpose and alternative + private boolean[][] destsAvailable; + private int[][] destsSample; + + // these will be used to keep the unique alternatives determined for the decision makers + HashMap altFreqMap; + private int[] sample; + private float[] corrections; + private int numUniqueAlts; + + private ChoiceModelApplication[] choiceModel; + + private String tourCategory; + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + + private int soaProbabilitiesCalculationCount = 0; + + + public DestinationSampleOfAlternativesModel( String soaUecFile, int sampleSize, HashMap propertyMap, ModelStructure modelStructure, String tourCategory, TazDataIf tazDataManager, DestChoiceSize dcSizeObj, DcSoaDMU dcSoaDmuObject ){ + + this.sampleSize = sampleSize; + this.dcSoaUecFileName = soaUecFile; + this.tourCategory = tourCategory; + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + // create an array of sample of alternative ChoiceModelApplication objects for each purpose + setupSampleOfAlternativesChoiceModelArrays( propertyMap, dcSizeObj, dcSoaDmuObject ); + + } + + + + + private void setupSampleOfAlternativesChoiceModelArrays( HashMap propertyMap, DestChoiceSize dcSizeObj, DcSoaDMU dcSoaDmuObject ) { + + String[] soaModelPurposeList = modelStructure.getDcModelPurposeList( tourCategory ); + + int minPurposeIndex = 99; + int maxPurposeIndex = 0; + for ( String purp : soaModelPurposeList ) { + int index = modelStructure.getDcModelPurposeIndex( purp ); + if ( index < minPurposeIndex ) + minPurposeIndex = index; + if ( index > maxPurposeIndex ) + maxPurposeIndex = index; + } + + choiceModel = new ChoiceModelApplication[maxPurposeIndex+1]; + probabilitiesCache = new double[maxPurposeIndex+1][]; + cumProbabilitiesCache = new double[maxPurposeIndex+1][]; + subtourProbabilitiesCache = new double[maxPurposeIndex+1][]; + subtourCumProbabilitiesCache = new double[maxPurposeIndex+1][]; + + + // for each purpose, get the number of segments + for ( String purp : soaModelPurposeList ) { + + int purposeIndex = modelStructure.getDcModelPurposeIndex( purp ); + + try { + int uecIndex = modelStructure.getSoaUecIndexForPurpose( purp ); + choiceModel[purposeIndex] = new ChoiceModelApplication ( dcSoaUecFileName, uecIndex, DC_SOA_DATA_SHEET, propertyMap, (VariableTable)dcSoaDmuObject ); + } + catch (RuntimeException e) { + logger.error ( String.format("exception caught setting up DC SOA ChoiceModelApplication[%d] for purpose=%s", purposeIndex, purp) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + } + + + setDcSizeForSampleOfAlternatives ( soaModelPurposeList, dcSizeObj ); + + altFreqMap = new HashMap( sampleSize ); + sample = new int[sampleSize+1]; + corrections = new float[sampleSize+1]; + } + + + + /** + * This method is called initially when the SOA choice models array is created. + * It would be called subsequently if a shadow pricing methodology is applied to reset the scaled size terms + * and corresponding availabilities and sample arrays. + */ + public void setDcSizeForSampleOfAlternatives ( String[] soaModelPurposeList, DestChoiceSize dcSizeObj ) { + + int numberOfZones = tazDataManager.getNumberOfZones(); + int numberOfSubzones = tazDataManager.getNumberOfSubZones(); + int numDcAlts = numberOfZones*numberOfSubzones; + + int[] altToZone = tazDataManager.getAltToZoneArray(); + int[] altToSubZone = tazDataManager.getAltToSubZoneArray(); + + + + // declare dimensions for the alternative availability array by purpose and number of alternaives + // set elements to true if size[purpose][alternative] > 0. Alternatives are numbered 1,...,ZONES*SUBZONES. + // set the destsSample to 1 if destsAvailable true - it is used in the UEC as a filter - if destsSample[purpose][k] == 0, the utility calculation is completely skipped. + int maxPurposeIndex = 0; + for ( String purp : soaModelPurposeList ) { + int index = modelStructure.getDcModelPurposeIndex( purp ); + if ( index > maxPurposeIndex ) + maxPurposeIndex = index; + } + + destsAvailable = new boolean[maxPurposeIndex+1][]; + destsSample = new int[maxPurposeIndex+1][]; + + for ( String purposeString : soaModelPurposeList ) { + + int p = modelStructure.getDcModelPurposeIndex( purposeString ); + + int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex( p ); + + destsAvailable[p] = new boolean[numDcAlts+1]; + destsSample[p] = new int[numDcAlts+1]; + + int k=0; + try { + for (k=1; k <= numDcAlts; k++) { + int zone = altToZone[k]; + int subzone = altToSubZone[k]; + double size = dcSizeObj.getDcSize( dcSizeArrayIndex, zone, subzone ); + if ( size > 0.0 ) { + destsAvailable[p][k] = true; + destsSample[p][k] = 1; + } + } // k + } + catch (RuntimeException e){ + logger.error ( String.format( "caught exception getting DC Size - p=%d, purposeString=%s, k=%d", p, purposeString, k)); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + } // p + + } + + + + public void computeDestinationSampleOfAlternatives( DcSoaDMU dcSoaDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex ) { + + // clear the HashMap used to store the alternatives selected and the count of each time an alternative was included + altFreqMap.clear(); + + + // get the origin taz for the person or tour + HouseholdIf hhObj = person.getHouseholdObject(); + + int homeTaz = hhObj.getHhTaz(); + int origTaz = homeTaz; + if ( tour != null ) + origTaz = tour.getTourOrigTaz(); + + // if the flag is set to compute sample of alternative probabilities for every work/school location choice, + // or the tour's origin taz is different from the currentOrigTaz, reset the currentOrigTaz and clear the stored probabilities. + if ( tour != null && tour.getTourCategoryIsAtWork() ) { + + if ( ALWAYS_COMPUTE_PROBABILITIES || origTaz != currentWorkTaz ) { + + // clear the probabilities store for the current origin taz, for each purpose + for ( int i=0; i < subtourProbabilitiesCache.length; i++ ) { + subtourProbabilitiesCache[i] = null; + subtourCumProbabilitiesCache[i] = null; + } + currentWorkTaz = origTaz; + + } + + // If the sample of alternatives choice probabilities have not been computed for the current origin taz + // and purpose specified, compute them. + if ( subtourProbabilitiesCache[purposeIndex] == null ) { + computeSampleOfAlternativesChoiceProbabilities( choiceModel[purposeIndex], dcSoaDmuObject, tour, person, purposeName, purposeIndex, origTaz ); + soaProbabilitiesCalculationCount++; + } + + } + else { + + if ( ALWAYS_COMPUTE_PROBABILITIES || origTaz != currentOrigTaz ) { + + // clear the probabilities store for the current origin taz, for each purpose + for ( int i=0; i < probabilitiesCache.length; i++ ) { + probabilitiesCache[i] = null; + cumProbabilitiesCache[i] = null; + } + currentOrigTaz = origTaz; + + } + + // If the sample of alternatives choice probabilities have not been computed for the current origin taz + // and purpose specified, compute them. + if ( probabilitiesCache[purposeIndex] == null ) { + computeSampleOfAlternativesChoiceProbabilities( choiceModel[purposeIndex], dcSoaDmuObject, tour, person, purposeName, purposeIndex, origTaz ); + soaProbabilitiesCalculationCount++; + } + + } + + + + + + Random hhRandom = hhObj.getHhRandom(); + int rnCount = hhObj.getHhRandomCount(); + // when household.getHhRandom() was applied, the random count was incremented, assuming a random number would be drawn right away. + // so let's decrement by 1, then increment the count each time a random number is actually drawn in this method. + rnCount --; + + // select sampleSize alternatives based on probabilitiesList[origTaz], and count frequency of alternatives chosen. + // final sample may include duplicate alternative selections. + for (int i=0; i < sampleSize; i++) { + + double rn = hhRandom.nextDouble(); + rnCount++; + + int chosenAlt = -1; + if ( tour != null && tour.getTourCategoryIsAtWork() ) + chosenAlt = choiceModel[purposeIndex].getChoiceIndexFromCumProbabilities( subtourCumProbabilitiesCache[purposeIndex], rn ); + else + chosenAlt = choiceModel[purposeIndex].getChoiceIndexFromCumProbabilities( cumProbabilitiesCache[purposeIndex], rn ); + + // write choice model alternative info to log file + if ( hhObj.getDebugChoiceModels () ) { + choiceModel[purposeIndex].logSelectionInfo ( String.format("%s Sample Of Alternatives Choice for dmuSegment=%d", purposeName, origTaz), String.format("HHID=%d, rn=%.8f, rnCount=%d", hhObj.getHhId(), rn, (rnCount+i) ), rn, chosenAlt ); + } + + + int freq = 0; + if ( altFreqMap.containsKey(chosenAlt) ) + freq = altFreqMap.get( chosenAlt ); + altFreqMap.put(chosenAlt, (freq + 1) ); + + } + + // sampleSize random number draws were made from the Random object for the current household, + // so update the count in the hh's Random. + hhObj.setHhRandomCount( rnCount ); + + + + // create arrays of the unique chosen alternatives and the frequency with which those alternatives were chosen. + numUniqueAlts = altFreqMap.size(); + Iterator it = altFreqMap.keySet().iterator(); + int k = 0; + while ( it.hasNext() ) { + + int alt = it.next(); + int freq = altFreqMap.get( alt ); + + double prob = 0; + if ( tour != null && tour.getTourCategoryIsAtWork() ) + prob = subtourProbabilitiesCache[purposeIndex][alt-1]; + else + prob = probabilitiesCache[purposeIndex][alt-1]; + + sample[k+1] = alt; + corrections[k+1] = (float)Math.log( (double)freq/prob ); + + k++; + } + + } + + + + /** + * @param choiceModel the ChoiceModelApplication object for the purpose + * @param tour the tour object for whic destination choice is required, or null if a usual work/school location is being chosen + * @param person the person object for whom the choice is being made + * @param purposeName the name of the purpose the choice is being made for - for logging + * @param purposeindex the index associated with the purpose + */ + private void computeSampleOfAlternativesChoiceProbabilities( ChoiceModelApplication choiceModel, DcSoaDMU dcSoaDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex, int origTaz ) { + + HouseholdIf hhObj = person.getHouseholdObject(); + + // set the hh object for this DMU object + dcSoaDmuObject.setHouseholdObject ( hhObj ); + + // set the person object for this DMU object + dcSoaDmuObject.setPersonObject ( person ); + + // set sample of alternatives choice DMU attributes + dcSoaDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), origTaz, 0 ); + + + // If the person making the choice is from a household requesting trace information, + // create a trace logger header and write prior to the choiceModel computing utilities + if ( hhObj.getDebugChoiceModels () ) { + + // prepare a trace log header that the choiceModel object will write prior to UEC trace logging + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + + if ( tour == null ) { + // null tour means the SOA choice is for a mandatory usual location choice + choiceModelDescription = String.format ( "Usual Location Sample of Alternatives Choice Model for: Category=%s, Purpose=%s", tourCategory, purposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType() ); + } + else { + choiceModelDescription = String.format ( "Destination Choice Model for: Category=%s, Purpose=%s, TourId=%d", tourCategory, purposeName, tour.getTourId() ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType() ); + } + + // log headers to traceLogger if the person making the choice is from a household requesting trace information + choiceModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + choiceModel.computeUtilities ( dcSoaDmuObject, dcSoaDmuObject.getDmuIndexValues(), destsAvailable[purposeIndex], destsSample[purposeIndex] ); + + + // the following order of assignment is important in mult-threaded context. + // probabilitiesCache[][] is a trigger variable - if it is not null for any thread, the cumProbabilitiesCache[][] values + // are used immediately, so the cumProbabilitiesCache values must be assigned before the probabilitiesCache + // are assigned, which indicates cumProbabilitiesCache[][] values are ready to be used. + if ( tour != null && tour.getTourCategoryIsAtWork() ) { + subtourCumProbabilitiesCache[purposeIndex] = choiceModel.getCumulativeProbabilities(); + subtourProbabilitiesCache[purposeIndex] = choiceModel.getProbabilities(); + } + else { + cumProbabilitiesCache[purposeIndex] = choiceModel.getCumulativeProbabilities(); + probabilitiesCache[purposeIndex] = choiceModel.getProbabilities(); + } + + + + // If the person making the choice is from a household requesting trace information, + // write choice model alternative info to the debug log file + if ( hhObj.getDebugChoiceModels () ) { + choiceModel.logAlternativesInfo ( String.format("%s Sample Of Alternatives Choice for origTaz=%d", purposeName, origTaz), String.format("HHID=%d", hhObj.getHhId()) ); + } + + } + + + + public int getSoaProbabilitiesCalculationCount() { + return soaProbabilitiesCalculationCount; + } + + public int getNumUniqueAlts() { + return numUniqueAlts; + } + + public int[] getSampleOfAlternatives() { + return sample; + } + + public float[] getSampleOfAlternativesCorrections() { + return corrections; + } + + public int getCurrentOrigTaz() { + return currentOrigTaz; + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourDepartureAndDurationTime.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourDepartureAndDurationTime.java new file mode 100644 index 0000000..9aa50e6 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourDepartureAndDurationTime.java @@ -0,0 +1,637 @@ +package com.pb.models.ctrampIf.jppf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.*; + + +import com.pb.common.calculator.VariableTable; +import com.pb.common.datafile.OLD_CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourDepartureTimeAndDurationDMU; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.Util; +import com.pb.common.newmodel.ChoiceModelApplication; +// +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 11, 2008 + * Time: 9:25:30 AM + * To change this template use File | Settings | File Templates. + */ +public class HouseholdAtWorkSubtourDepartureAndDurationTime implements Serializable { + + + private transient Logger logger = Logger.getLogger( HouseholdAtWorkSubtourDepartureAndDurationTime.class ); + private transient Logger todLogger = Logger.getLogger( "todLogger" ); + private transient Logger tourMCNonManLogger = Logger.getLogger( "tourMcNonMan" ); + + + private static final String TOD_UEC_FILE_TARGET = "UecFile.TourDepartureTimeAndDuration"; + private static final String TOD_UEC_DATA_TARGET = "departTime.data.page"; + private static final String TOD_UEC_AT_WORK_MODEL_TARGET = "departTime.atwork.page"; + + private static final String PROPERTIES_UEC_TOUR_MODE_CHOICE = "UecFile.TourModeChoice"; + private static final String PROPERTIES_UEC_DEP_TIME_AND_DUR = "UecFile.TourDepartureTimeAndDuration"; + + + private static String[] tourPurposeNames; + + private int[] todModelIndices; + private HashMap purposeNameIndexMap; + + private static final String[] dcModelSheetKeys = { + TOD_UEC_AT_WORK_MODEL_TARGET, + TOD_UEC_AT_WORK_MODEL_TARGET, + TOD_UEC_AT_WORK_MODEL_TARGET + }; + + private int[] tourDepartureTimeChoiceSample; + + + // DMU for the UEC + private TourDepartureTimeAndDurationDMU todDmuObject; + private TourModeChoiceDMU mcDmuObject; + + // model structure to compare the .properties time of day with the UECs + private ModelStructure modelStructure; + + private ChoiceModelApplication[] todModels; + private ModeChoiceModel mcModel; + + private int[] altStarts; + private int[] altEnds; + + private boolean[] needToComputeLogsum; + private double[] modeChoiceLogsums; + + private byte[] tempWindow; + + // create an array to count the subtours propcessed within work tours + // there are at most 2 work tours per person + private int[] subtourNumForWorkTours = new int[2]; + + private int noAltChoice = 1; + + + + public HouseholdAtWorkSubtourDepartureAndDurationTime( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + // set the model structure + this.modelStructure = modelStructure; + this.mcModel = mcModel; + + logger.info(String.format("setting up %s time-of-day choice model.", ModelStructure.AT_WORK_CATEGORY)); + + setupTodChoiceModels( propertyMap, dmuFactory ); + } + + + private void setupTodChoiceModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String todUecFileName = propertyMap.get( TOD_UEC_FILE_TARGET ); + todUecFileName = projectDirectory + todUecFileName; + + todDmuObject = dmuFactory.getTourDepartureTimeAndDurationDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + int numLogsumIndices = modelStructure.getPeriodCombinationIndices().length; + needToComputeLogsum = new boolean[numLogsumIndices]; + modeChoiceLogsums = new double[numLogsumIndices]; + + tourPurposeNames = new String[3]; + tourPurposeNames[0] = modelStructure.AT_WORK_BUSINESS_PURPOSE_NAME; + tourPurposeNames[1] = modelStructure.AT_WORK_EAT_PURPOSE_NAME; + tourPurposeNames[2] = modelStructure.AT_WORK_MAINT_PURPOSE_NAME; + + // create the array of tod model indices + int[] uecSheetIndices = new int[tourPurposeNames.length]; + + purposeNameIndexMap = new HashMap(tourPurposeNames.length); + + int i = 0; + for ( String purposeName : tourPurposeNames ) { + int uecIndex = Util.getIntegerValueFromPropertyMap( propertyMap, dcModelSheetKeys[i]); + purposeNameIndexMap.put(purposeName, i); + uecSheetIndices[i] = uecIndex; + i++; + } + + + // create a lookup array to map purpose index to model index + todModelIndices = new int[uecSheetIndices.length]; + + // get a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + // also create a HashMap to relate size segment index to SOA Model objects + HashMap modelIndexMap = new HashMap(); + int todModelIndex = 0; + int todSegmentIndex = 0; + for ( int uecIndex : uecSheetIndices ) { + // if the uec sheet for the model segment is not in the map, add it, otherwise, get it from the map + if ( ! modelIndexMap.containsKey(uecIndex) ) { + modelIndexMap.put( uecIndex, todModelIndex ); + todModelIndices[todSegmentIndex] = todModelIndex++; + } + else { + todModelIndices[todSegmentIndex] = modelIndexMap.get( uecIndex ); + } + + todSegmentIndex++; + } + + + todModels = new ChoiceModelApplication[modelIndexMap.size()]; + int todModelDataSheet = Util.getIntegerValueFromPropertyMap( propertyMap, TOD_UEC_DATA_TARGET ); + + for (int uecIndex : modelIndexMap.keySet() ) + { + int modelIndex = modelIndexMap.get(uecIndex); + try + { + todModels[modelIndex] = new ChoiceModelApplication( todUecFileName, uecIndex, todModelDataSheet, propertyMap, (VariableTable) todDmuObject); + } catch (RuntimeException e) + { + logger.error( String.format("exception caught setting up At-work Subtour TOD ChoiceModelApplication[%d] for model index=%d of %d models", i, i, modelIndexMap.size()) ); + logger.fatal("Exception caught:", e); + logger.fatal("Throwing new RuntimeException() to terminate."); + throw new RuntimeException(); + } + + } + + + // get the alternatives table from the work tod UEC. + TableDataSet altsTable = todModels[0].getUEC().getAlternativeData(); + + altStarts = altsTable.getColumnAsInt( CtrampApplication.START_FIELD_NAME ); + altEnds = altsTable.getColumnAsInt( CtrampApplication.END_FIELD_NAME ); + todDmuObject.setTodAlts(altStarts, altEnds); + + int numDepartureTimeChoiceAlternatives = todModels[0].getNumberOfAlternatives(); + tourDepartureTimeChoiceSample = new int[numDepartureTimeChoiceAlternatives+1]; + Arrays.fill ( tourDepartureTimeChoiceSample, 1 ); + + tempWindow = new byte[modelStructure.getNumberOfTimePeriods()+1]; + + } + + + + public void applyModel( HouseholdIf hh, boolean runModeChoice ){ + + Logger modelLogger = todLogger; + + + // get the peron objects for this household + PersonIf[] persons = hh.getPersons(); + for ( int p=1; p < persons.length; p++ ) { + + PersonIf person = persons[p]; + + // get the work tours for the person + ArrayList subtourList = person.getListOfAtWorkSubtours(); + + // if no work subtours for person, nothing to do. + if ( subtourList.size() == 0 ) + continue; + + ArrayList workTourList = person.getListOfWorkTours(); + + // save a copy of this person's original time windows + byte[] personWindow = person.getTimeWindows(); + for (int w=0; w < personWindow.length; w++) + tempWindow[w] = personWindow[w]; + + for (int i=0; i < subtourNumForWorkTours.length; i++) + subtourNumForWorkTours[i] = 0; + + int m = -1; + int tourPurpNum = 1; + int noWindowCountFirstTemp = 0; + int noWindowCountLastTemp = 0; + int noLaterAlternativeCountTemp = 0; + for ( TourIf t : subtourList ) { + + TourIf workTour = null; + int workTourIndex = 0; + + try { + + workTourIndex = t.getWorkTourIndexFromSubtourId( t.getTourId() ); + subtourNumForWorkTours[workTourIndex]++; + workTour = workTourList.get( workTourIndex ); + + // if the first subtour for a work tour, make window of work tour available, and other windows not available + if ( subtourNumForWorkTours[workTourIndex] == 1 ) { + person.resetTimeWindow(workTour.getTourDepartPeriod(), workTour.getTourArrivePeriod()); + person.scheduleWindow(0, workTour.getTourDepartPeriod()-1); + person.scheduleWindow(workTour.getTourArrivePeriod()+1, modelStructure.getNumberOfTimePeriods()); + } + else if ( subtourNumForWorkTours[workTourIndex] > 2 ) { + logger.error ( "too many subtours for a work tour. workTourIndex=" + workTourIndex + ", subtourNumForWorkTours[workTourIndex]=" + subtourNumForWorkTours[workTourIndex] ); + logger.error ( "tourID=" + t.getTourId() + ", workTourIndexFromSubtourId=" + t.getWorkTourIndexFromSubtourId(t.getTourId()) ); + logger.error ( "num subtours=" + subtourList.size() + ", num work tours=" + workTourList.size() ); + logger.error ( "hhid=" + hh.getHhId() + ", persNum=" + person.getPersonNum() ); + hh.logHouseholdObject("", logger); + hh.logPersonObject("", logger, person); + hh.logTourObject("", logger, person, t ); + throw new RuntimeException(); + } + + + // get the choice model for the tour purpose + String tourPurposeName = t.getSubTourPurpose(); + + int tourPurposeIndex = purposeNameIndexMap.get( tourPurposeName ); + m = todModelIndices[tourPurposeIndex]; + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( hh.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "AtWork Subtour Departure Time Choice Model for: Purpose=%s", tourPurposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d, num=%d of %d %s tours", hh.getHhId(), person.getPersonNum(), person.getPersonType(), t.getTourId(), tourPurpNum, subtourList.size(), tourPurposeName ); + todModels[m].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + String loggerString = "AtWork Subtour Departure Time Choice Model: Debug Statement for Household ID: " + hh.getHhId() + ", Person Num: " + person.getPersonNum() + ", Person Type: " + person.getPersonType() + ", Tour Id: " + t.getTourId() + ", num " + tourPurpNum + " of " + subtourList.size() + " " + tourPurposeName + " tours."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + } + + // set the dmu object + todDmuObject.setHousehold( hh ); + todDmuObject.setPerson( person ); + todDmuObject.setTour( t ); + + int destinationTaz = t.getTourDestTaz(); + todDmuObject.setDestinationZone( destinationTaz ); + + int originTaz = t.getTourOrigTaz(); + todDmuObject.setOriginZone( originTaz ); + + int otherTourEndHour = -1; + + // check for multiple tours for this person, by purpose + // set the first or second switch if multiple tours for person, by purpose + if ( subtourList.size() == 1 ) { + // not a multiple tour pattern + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( 1 ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else if ( subtourList.size() > 1 ) { + // Two-plus tour multiple tour pattern + if ( tourPurpNum == 1 ) { + // first of 2+ tours + todDmuObject.setFirstTour( 1 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( tourPurpNum ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else { + // 2nd or greater tours + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 1 ); + todDmuObject.setTourNumber( tourPurpNum ); + // the ArrayList is 0-based, and we want the previous tour, so subtract 2 from tourPurpNum to get the right index + otherTourEndHour = subtourList.get( tourPurpNum-2 ).getTourArrivePeriod(); + todDmuObject.setEndOfPreviousScheduledTour( otherTourEndHour ); + } + } + + + + // set the choice availability and sample + boolean[] departureTimeChoiceAvailability = person.getAvailableTimeWindows( altStarts, altEnds ); + Arrays.fill(tourDepartureTimeChoiceSample, 1); + + if ( departureTimeChoiceAvailability.length != tourDepartureTimeChoiceSample.length ) { + logger.error( String.format( "error in at-work subtour departure time choice model for hhId=%d, personNum=%d, tour purpose index=%d, tour ArrayList index=%d.", hh.getHhId(), person.getPersonNum(), tourPurposeIndex, tourPurpNum-1 )); + logger.error( String.format( "length of the availability array determined by the number of alternatives set in the person scheduler=%d", departureTimeChoiceAvailability.length )); + logger.error( String.format( "does not equal the length of the sample array determined by the number of alternatives in the at-work subtour UEC=%d.", tourDepartureTimeChoiceSample.length )); + throw new RuntimeException(); + } + + + // if no time window is available for the tour, make the first and last alternatives available + // for that alternative, and keep track of the number of times this condition occurs. + int alternativeAvailable = -1; + for (int a=0; a < departureTimeChoiceAvailability.length; a++) { + if ( departureTimeChoiceAvailability[a] ) { + alternativeAvailable = a; + break; + } + } + + int chosen = -1; + int chosenStartPeriod = -1; + int chosenEndPeriod = -1; + + + // alternate making the first and last periods chosen if no alternatives are available + if ( alternativeAvailable < 0 ) { + + if ( noAltChoice == 1 ) { + if ( subtourList.size() > 1 && tourPurpNum > 1 ) { + chosenStartPeriod = otherTourEndHour; + chosenEndPeriod = otherTourEndHour; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, depart AND arrive set to previous sub-tour arrive period=" + chosenStartPeriod + "." ); + } + else { + chosenStartPeriod = workTour.getTourDepartPeriod(); + chosenEndPeriod = workTour.getTourDepartPeriod(); + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled and no previous sub-tour, depart AND arrive set to work tour depart period=" + chosenStartPeriod + "." ); + } + noWindowCountFirstTemp++; + noAltChoice = departureTimeChoiceAvailability.length-1; + + } else { + + if ( subtourList.size() > 1 && tourPurpNum > 1 ) { + chosenStartPeriod = otherTourEndHour; + chosenEndPeriod = otherTourEndHour; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, depart AND arrive set to previous sub-tour arrive period=" + chosenStartPeriod + "." ); + } + else { + chosenStartPeriod = workTour.getTourArrivePeriod(); + chosenEndPeriod = workTour.getTourArrivePeriod(); + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled and no previous sub-tour, depart AND arrive set to work tour arrive period=" + chosenStartPeriod + "." ); + } + noWindowCountLastTemp++; + noAltChoice = 1; + } + + // schedule the chosen alternative + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + + if ( runModeChoice ) { + + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre At-work Subtour Tour Mode Choice Household " + hh.getHhId() + ", Tour " + tourPurpNum + " of " + subtourList.size(), modelLogger ); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(hh, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + + } + else { + + // calculate and store the mode choice logsum for the usual work location for this worker at the various + // departure time and duration alternativees + setTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( t, departureTimeChoiceAvailability ); + + + if( hh.getDebugChoiceModels() ){ + hh.logTourObject( loggingHeader, modelLogger, person, t ); + } + + todModels[m].computeUtilities ( todDmuObject, todDmuObject.getIndexValues(), departureTimeChoiceAvailability, tourDepartureTimeChoiceSample ); + + Random hhRandom = hh.getHhRandom(); + int randomCount = hh.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + if ( todModels[m].getAvailabilityCount() > 0 ) + { + chosen = todModels[m].getChoiceResult( rn ); + + // debug output + if( hh.getDebugChoiceModels() ){ + + double[] utilities = todModels[m].getUtilities(); + double[] probabilities = todModels[m].getProbabilities(); + boolean[] availabilities = todModels[m].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + ", Tour Id: " + t.getTourId() + ", Tour num: " + tourPurpNum + " of " + subtourList.size() + " " + tourPurposeName + " tours." ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < todModels[m].getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d out=%-3d, in=%-3d", k+1, altStarts[k], altEnds[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d out=%-3d, in=%-3d", chosen, altStarts[chosen-1], altEnds[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + todModels[m].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + todModels[m].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s for %s", choiceModelDescription, decisionMakerLabel ); + todModels[m].logUECResults( modelLogger, loggingHeader ); + + } + + } + else { + + // since there were no alternatives with valid utility, assuming previous + // tour of this type scheduled up to the last period, so no periods left + // for this tour. + + //TODO: do a formal check for this so we can still flag other reasons why there's + // no valid utility for any alternative + chosen = departureTimeChoiceAvailability.length-1; + noLaterAlternativeCountTemp++; + + } + + // schedule the chosen alternative + chosenStartPeriod = altStarts[chosen-1]; + chosenEndPeriod = altEnds[chosen-1]; + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + + + if ( runModeChoice ) { + + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre At-work Subtour Tour Mode Choice Household " + hh.getHhId() + ", Tour " + tourPurpNum + " of " + subtourList.size(), tourMCNonManLogger ); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(hh, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + + } + catch ( Exception e ) { + String errorMessage = String.format( "Exception caught for HHID=%d, personNum=%d, At-work Subtour Departure time choice, tour ArrayList index=%d.", hh.getHhId(), person.getPersonNum(), tourPurpNum-1 ); + String decisionMakerLabel = String.format ( "Final At-work Subtour Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", hh.getHhId(), person.getPersonNum(), person.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, person ); + todModels[m].logUECResults( modelLogger, errorMessage ); + + logger.error ( errorMessage, e ); + throw new RuntimeException(); + } + + tourPurpNum++; + + } + + for (int w=0; w < person.getTimeWindows().length; w++) + person.getTimeWindows()[w] = tempWindow[w]; + + + if ( hh.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "Final At-work Subtour Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", hh.getHhId(), person.getPersonNum(), person.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + } + + hh.setInmtodRandomCount( hh.getHhRandomCount() ); + + } + + + private void setModeChoiceDmuAttributes(HouseholdIf household, PersonIf person, TourIf t, int startPeriod, int endPeriod) + { + + t.setTourDepartPeriod(startPeriod); + t.setTourArrivePeriod(endPeriod); + + int workTourIndex = t.getWorkTourIndexFromSubtourId( t.getTourId() ); + TourIf workTour = person.getListOfWorkTours().get( workTourIndex ); + + // update the MC dmuObjects for this person + mcDmuObject.setHouseholdObject(household); + mcDmuObject.setPersonObject(person); + mcDmuObject.setTourObject(t); + mcDmuObject.setWorkTourObject(workTour); + mcDmuObject.setDmuIndexValues(household.getHhId(), t.getTourOrigTaz(), t.getTourOrigTaz(), t.getTourDestTaz(), household.getDebugChoiceModels()); + + //create TVPB for tour mode choice model + mcModel.setTVPBValues(mcDmuObject, t.getTourPrimaryPurpose()); + + } + + + private void setTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( TourIf tour, boolean[] altAvailable ) + { + + PersonIf person = tour.getPersonObject(); + HouseholdIf household = person.getHouseholdObject(); + + Arrays.fill(needToComputeLogsum, true); + Arrays.fill(modeChoiceLogsums, -999); + + Logger modelLogger = todLogger; + String choiceModelDescription = String.format( "At-work Subtour Mode Choice Logsum calculation for %s Departure Time Choice", tour.getTourPrimaryPurpose() ); + String decisionMakerLabel = String.format( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId(), person.getListOfWorkTours().size()); + String loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + + + for (int a = 1; a <= altStarts.length; a++) + { + + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! altAvailable[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + if (needToComputeLogsum[index]) + { + + String periodString = modelStructure.getPeriodLabel( modelStructure.getPeriodIndex(startPeriod)) + " to " + modelStructure.getPeriodLabel( modelStructure.getPeriodIndex(endPeriod)); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, tour, startPeriod, endPeriod); + + if (household.getDebugChoiceModels()) + household.logTourObject(loggingHeader + ", " + periodString, modelLogger, + person, mcDmuObject.getTourObject()); + + try + { + modeChoiceLogsums[index] = mcModel.getModeChoiceLogsum(mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel + ", " + periodString); + } catch(Exception e) + { + logger.fatal( "exception caught applying mcModel.getModeChoiceLogsum() for " + periodString + " work tour." ); + logger.fatal( "choiceModelDescription = " + choiceModelDescription ); + logger.fatal( "decisionMakerLabel = " + decisionMakerLabel ); + throw new RuntimeException(e); + } + needToComputeLogsum[index] = false; + } + + } + + todDmuObject.setModeChoiceLogsums(modeChoiceLogsums); + + mcDmuObject.getTourObject().setTourDepartPeriod(0); + mcDmuObject.getTourObject().setTourArrivePeriod(0); + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourFrequencyModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourFrequencyModel.java new file mode 100644 index 0000000..af33397 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAtWorkSubtourFrequencyModel.java @@ -0,0 +1,328 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Random; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +// +import com.pb.models.ctrampIf.AtWorkSubtourFrequencyDMU; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; + +public class HouseholdAtWorkSubtourFrequencyModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdAtWorkSubtourFrequencyModel.class); + private transient Logger tourFreq = Logger.getLogger("tourFreq"); + + private static final String PROPERTIES_UEC_AT_WORK_SUBTOUR_FREQ = "UecFile.AtWorkSubtourFrequency"; + + private static final int UEC_DATA_PAGE = 0; + private static final int UEC_MODEL_PAGE = 1; + + + // model results + //private static final int NO_SUBTOURS = 1; + private static final int ONE_EAT = 2; + private static final int ONE_BUSINESS = 3; + private static final int ONE_MAINT = 4; + private static final int TWO_BUSINESS = 5; + private static final int ONE_EAT_ONE_BUSINESS = 6; + + + + + private int[] areaType; + private int[] zoneTableRow; + + //protected HashMap countByPersonType; + + private AtWorkSubtourFrequencyDMU dmuObject; + private ChoiceModelApplication choiceModelApplication; + + private ModelStructure modelStructure; + private String[] alternativeNames; + + + /** + * Constructor establishes the ChoiceModelApplication, which applies the logit model via the UEC + * spreadsheet. + * @param dmuObject is the UEC dmu object for this choice model + * @param uecFileName is the UEC control file name + * @param resourceBundle is the application ResourceBundle, from which a properties file HashMap will be created for the UEC + * @param tazDataManager is the object used to interact with the zonal data table + * @param modelStructure is the ModelStructure object that defines segmentation and other model structure relate atributes + */ + public HouseholdAtWorkSubtourFrequencyModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ){ + + this.modelStructure = modelStructure; + + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + + setUpModels( propertyMap, dmuFactory ); + + } + + + private void setUpModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( String.format( "setting up %s tour frequency choice model.", ModelStructure.AT_WORK_CATEGORY ) ); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String uecFileName = propertyMap.get( PROPERTIES_UEC_AT_WORK_SUBTOUR_FREQ ); + uecFileName = projectDirectory + uecFileName; + + + dmuObject = dmuFactory.getAtWorkSubtourFrequencyDMU(); + + // set up the model + choiceModelApplication = new ChoiceModelApplication(uecFileName, UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + + } + + + /** + * Applies the model for the array of households that are stored in the HouseholdDataManager. + * The results are summarized by person type. + * + * @param householdDataManager is the object containg the Household objects for which this model is to be applied. + */ + public void applyModel( HouseholdIf household ){ + + int choice = -1; + String personTypeString = ""; + + Logger modelLogger = tourFreq; + if ( household.getDebugChoiceModels() ) + household.logHouseholdObject( "Pre AtWork Subtour Frequency Choice HHID=" + household.getHhId() + " Object", modelLogger ); + + + // prepare the results array + //countByPersonType = new HashMap(); + + // get this household's person array + PersonIf[] personArray = household.getPersons(); + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + dmuObject.setHouseholdObject(household); + + // loop through the person array (1-based) + for(int j=1;j tourList = person.getListOfWorkTours(); + if ( tourList == null ) + continue; + + + + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + + int workTourIndex = 0; + for ( TourIf workTour : tourList ) { + + // set the area type for the work taz + int tableRow = zoneTableRow[ workTour.getTourDestTaz() ]; + dmuObject.setWorkTazAreaType( areaType[tableRow-1] ); + + + try { + + // set the person and tour object + dmuObject.setPersonObject( person ); + dmuObject.setTourObject( workTour ); + + // write debug header + if(household.getDebugChoiceModels()){ + + choiceModelDescription = String.format ( "At-work Subtour Frequency Choice Model:" ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, workTourId=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), workTour.getTourId() ); + choiceModelApplication.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + String loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + + } + + + // set the availability array for the tour frequency model + alternativeNames = choiceModelApplication.getAlternativeNames(); + int numberOfAlternatives = alternativeNames.length; + boolean[] availabilityArray = new boolean[numberOfAlternatives+1]; + Arrays.fill( availabilityArray, true ); + + // create the sample array + int[] sampleArray = new int[availabilityArray.length]; + Arrays.fill(sampleArray, 1); + + + // compute the utilities + IndexValues index = dmuObject.getDmuIndexValues(); + index.setHHIndex( household.getHhId() ); + index.setZoneIndex( household.getHhTaz() ); + index.setOriginZone( workTour.getTourOrigTaz() ); + index.setDestZone( workTour.getTourDestTaz() ); + index.setDebug( household.getDebugChoiceModels() ); + + + if( household.getDebugChoiceModels() ){ + household.logTourObject( loggingHeader, modelLogger, person, workTour ); + } + + choiceModelApplication.computeUtilities(dmuObject, index, availabilityArray, sampleArray); + + + // get the random number from the household + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + if ( choiceModelApplication.getAvailabilityCount() > 0 ) + choice = choiceModelApplication.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for j=%d, tourNum=%d, HHID=%d, no available at-work frequency alternatives to choose from in choiceModelApplication.", j, workTourIndex, person.getHouseholdObject().getHhId() ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = choiceModelApplication.getUtilities(); + double[] probabilities = choiceModelApplication.getProbabilities(); + + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("-------------------- -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < alternativeNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %-16s", k+1, alternativeNames[k] ); + modelLogger.info(String.format("%-20s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %-16s", choice, alternativeNames[choice-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + choiceModelApplication.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + choiceModelApplication.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, choice ); + + // write UEC calculation results to separate model specific log file + choiceModelApplication.logUECResults( modelLogger, loggingHeader ); + + } + + + + workTour.setSubtourFreqChoice( choice ); + + // set the person choices + if( choice == ONE_EAT ) { + int id = workTour.getSubtourIdFromIndices(workTourIndex, 1); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkEatPurposeName(), modelStructure ); + } + else if( choice == ONE_BUSINESS ) { + int id = workTour.getSubtourIdFromIndices(workTourIndex, 1); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkBusinessPurposeName(), modelStructure ); + } + else if( choice == ONE_MAINT ) { + int id = workTour.getSubtourIdFromIndices(workTourIndex, 1); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkMaintPurposeName(), modelStructure ); + } + else if( choice == TWO_BUSINESS ) { + int id = workTour.getSubtourIdFromIndices(workTourIndex, 1); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkBusinessPurposeName(), modelStructure ); + id = workTour.getSubtourIdFromIndices(workTourIndex, 2); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkBusinessPurposeName(), modelStructure ); + } + else if( choice == ONE_EAT_ONE_BUSINESS ) { + int id = workTour.getSubtourIdFromIndices(workTourIndex, 1); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkEatPurposeName(), modelStructure ); + id = workTour.getSubtourIdFromIndices(workTourIndex, 2); + person.createAtWorkSubtour( id, choice, workTour.getTourDestTaz(), workTour.getTourDestWalkSubzone(), modelStructure.getAtWorkBusinessPurposeName(), modelStructure ); + } + + + + // count the results by person type +// if(countByPersonType.containsKey(personTypeString)){ +// +// int[] counterArray = countByPersonType.get(personTypeString); +// counterArray[choice-1]++; +// countByPersonType.put(personTypeString, counterArray); +// +// } +// else{ +// +// int[] counterArray = new int[alternativeNames.length]; +// counterArray[choice-1]++; +// countByPersonType.put(personTypeString, counterArray); +// +// } // is personType in map if + + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught for j=%d, tourNum=%d, HHID=%d.", j, workTourIndex, household.getHhId() ) ); + throw new RuntimeException(); + } + + + workTourIndex++; + + } + + } // j (person loop) + + household.setAwfRandomCount( household.getHhRandomCount() ); + + } + + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdAutoOwnershipModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAutoOwnershipModel.java new file mode 100644 index 0000000..50dea5c --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdAutoOwnershipModel.java @@ -0,0 +1,541 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; +import java.util.ResourceBundle; + +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.AutoOwnershipChoiceDMU; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TimeDMU; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.common.newmodel.UtilityExpressionCalculator; +import com.pb.common.util.ResourceUtil; +import com.pb.common.newmodel.ChoiceModelApplication; + +import com.pb.cmap.tvpb.TapPair; +import com.pb.cmap.tvpb.TransitVirtualPathBuilder; +import com.pb.cmap.tvpb.Trip; + +import org.apache.log4j.Logger; + + +public class HouseholdAutoOwnershipModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdAutoOwnershipModel.class); + private transient Logger aoLogger = Logger.getLogger("ao"); + + + private static final String AO_CONTROL_FILE_TARGET = "UecFile.AutoOwnership"; + private static final int AO_DATA_SHEET = 0; + private static final int AO_MODEL_SHEET = 1; + private static final int AUTO_MODEL_SHEET = 2; + private static final int TRANSIT_MODEL_SHEET = 3; + private static final int WALK_MODEL_SHEET = 4; + + + ChoiceModelApplication aoModel; + AutoOwnershipChoiceDMU aoDmuObject; + private ModelStructure modelStructure; + + private AutoDependencyModel adModel; + private TourModeChoiceDMU mcDmuObject; + HashMap propertyMap; + + UtilityExpressionCalculator[] timeUec; + + TransitVirtualPathBuilder tvpb; + + public HouseholdAutoOwnershipModel( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory, TazDataIf tazDataManager, ModelStructure modelStructure) { + + // setup the auto ownership choice model objects + setupAutoOwnershipChoiceModelApplication( propertyMap, dmuFactory, tazDataManager, modelStructure); + + } + + + private void setupAutoOwnershipChoiceModelApplication( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory, TazDataIf tazDataManager, ModelStructure modelStructure ) { + + logger.info( "setting up AO choice model." ); + + this.propertyMap = propertyMap; + this.modelStructure = modelStructure; + + // locate the auto ownership UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String autoOwnershipUecFile = propertyMap.get( AO_CONTROL_FILE_TARGET); + autoOwnershipUecFile = projectDirectory + autoOwnershipUecFile; + + // create the auto ownership choice model DMU object. + aoDmuObject = dmuFactory.getAutoOwnershipDMU(); + aoDmuObject.setupTazDataManager(tazDataManager); + + + // create the auto ownership choice model object + aoModel = new ChoiceModelApplication( autoOwnershipUecFile, AO_MODEL_SHEET, AO_DATA_SHEET, propertyMap, (VariableTable)aoDmuObject ); + + //create auto dependency model + mcDmuObject = dmuFactory.getModeChoiceDMU(); + adModel = new AutoDependencyModel( propertyMap, modelStructure, ModelStructure.MANDATORY_CATEGORY, dmuFactory ); + + TimeDMU timeDmu = new TimeDMU(); + + // create a set of UEC objects to use to get OD times for the selected long term location + timeUec = new UtilityExpressionCalculator[3]; + timeUec[0] = new UtilityExpressionCalculator(new File(autoOwnershipUecFile), AUTO_MODEL_SHEET, AO_DATA_SHEET, propertyMap, (VariableTable)timeDmu ); + timeUec[1] = new UtilityExpressionCalculator(new File(autoOwnershipUecFile), TRANSIT_MODEL_SHEET, AO_DATA_SHEET, propertyMap, (VariableTable)timeDmu ); + timeUec[2] = new UtilityExpressionCalculator(new File(autoOwnershipUecFile), WALK_MODEL_SHEET, AO_DATA_SHEET, propertyMap, (VariableTable)timeDmu ); + + + //create TVPB for auto dependency model + tvpb = new TransitVirtualPathBuilder(propertyMap); + tvpb.setupTVPB(); + tvpb.setupModels(); + tvpb.setMTTData(tazDataManager.getMttData()); + } + + + public void applyModel( HouseholdIf hhObject ){ + + if ( hhObject.getDebugChoiceModels() ) + hhObject.logHouseholdObject( "Pre AO Household " + hhObject.getHhId() + " Object", aoLogger ); + + int chosen = getAutoOwnershipChoice( hhObject ); + hhObject.setAutoOwnershipModelResult((short)chosen); + + } + + + private int getAutoOwnershipChoice ( HouseholdIf hhObj ) { + + // update the AO dmuObject for this hh + aoDmuObject.setHouseholdObject( hhObj ); + aoDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), 0 ); + + // set the travel times from home to chosen work and school locations + double workTimeSavings = getWorkTourAutoTimeSavings( hhObj ); + double schoolDriveTimeSavings = getSchoolDriveTourAutoTimeSavings( hhObj ); + double schoolNonDriveTimeSavings = getSchoolNonDriveTourAutoTimeSavings( hhObj ); + + aoDmuObject.setWorkTourAutoTimeSavings( workTimeSavings ); + aoDmuObject.setSchoolDriveTourAutoTimeSavings( schoolDriveTimeSavings ); + aoDmuObject.setSchoolNonDriveTourAutoTimeSavings( schoolNonDriveTimeSavings ); + + //calculate work and school auto dependency terms + aoDmuObject.setWorkAutoDependency(getWorkAutoDependency(hhObj)); + aoDmuObject.setSchoolAutoDependency(getSchoolAutoDependency(hhObj)); + + // compute utilities and choose auto ownership alternative. + aoModel.computeUtilities ( aoDmuObject, aoDmuObject.getDmuIndexValues() ); + + Random hhRandom = hhObj.getHhRandom(); + int randomCount = hhObj.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosenAlt; + if ( aoModel.getAvailabilityCount() > 0 ) { + chosenAlt = aoModel.getChoiceResult( rn ); + } + else { + logger.error ( String.format( "Exception caught for HHID=%d, no available auto ownership alternatives to choose from in choiceModelApplication.", hhObj.getHhId() ) ); + throw new RuntimeException(); + } + + + // write choice model alternative info to log file + if ( hhObj.getDebugChoiceModels() ) { + + double[] utilities = aoModel.getUtilities(); + double[] probabilities = aoModel.getProbabilities(); + + aoLogger.info("Alternative Utility Probability CumProb"); + aoLogger.info("-------------------- --------------- ------------ ------------"); + + double cumProb = 0.0; + for( int k=0; k < aoModel.getNumberOfAlternatives(); k++ ) { + cumProb += probabilities[k]; + aoLogger.info(String.format("%-20s%18.6e%18.6e%18.6e", k + " autos", utilities[k], probabilities[k], cumProb ) ); + } + + aoLogger.info(" "); + aoLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", chosenAlt, rn, randomCount ) ); + + aoLogger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + aoLogger.info(""); + aoLogger.info(""); + + + // write choice model alternative info to debug log file + aoModel.logAlternativesInfo ( "Household Auto Ownership Choice", String.format("HH_%d", hhObj.getHhId() ) ); + aoModel.logSelectionInfo ( "Household Auto Ownership Choice", String.format("HH_%d", hhObj.getHhId() ), rn, chosenAlt ); + + // write UEC calculation results to separate model specific log file + aoModel.logUECResults( aoLogger, String.format("Household Auto Ownership Choice, HH_%d", hhObj.getHhId() ) ); + } + + hhObj.setAoRandomCount( hhObj.getHhRandomCount() ); + + + return chosenAlt; + + } + + + private double getWorkTourAutoTimeSavings( HouseholdIf hhObj ) { + + double totalAutoSavingsRatio = 0.0; + + TimeDMU timeDmuObject = new TimeDMU (); + int[] availability = new int[2]; + availability[1] = 1; + + // determine the travel time savings from home to chosen work and school locations + // for workers ans sr=tudents by student category + PersonIf[] personArray = hhObj.getPersons(); + for ( int i=1; i < personArray.length; i++ ) { + + PersonIf person = personArray[i]; + + // if person is not a worker, skip to next person. + if ( person.getPersonIsWorker() == 0 ) + continue; + + + // use a time UEC to get the od times for this person's location choice + boolean debugFlag = hhObj.getDebugChoiceModels(); + timeDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), person.getUsualWorkLocation(), debugFlag ); + + double auto[] = timeUec[0].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double transit[] = timeUec[1].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double walk[] = timeUec[2].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + + // set the minimum of walk and transit time to walk time if no transit access, + // otherwise to the minimum of walk and transit time. + double minWalkTransit = walk[0]; + if ( transit[0] > 0 && transit[0] < walk[0] ) { + minWalkTransit = transit[0]; + } + + // set auto savings to be minimum of walk and transit time minus auto time + double autoSavings = minWalkTransit - auto[0]; + double autoSavingsRatio = ( autoSavings < 120 ? autoSavings/120.0 : 1.0 ); + + totalAutoSavingsRatio += autoSavingsRatio; + + } + + return totalAutoSavingsRatio; + + } + + + private double getSchoolDriveTourAutoTimeSavings( HouseholdIf hhObj ) { + + double totalAutoSavingsRatio = 0.0; + + TimeDMU timeDmuObject = new TimeDMU (); + int[] availability = new int[2]; + availability[1] = 1; + + // determine the travel time savings from home to chosen work and school locations + // for workers ans sr=tudents by student category + PersonIf[] personArray = hhObj.getPersons(); + for ( int i=1; i < personArray.length; i++ ) { + + PersonIf person = personArray[i]; + + + // if person is not a worker, skip to next person. + if ( person.getPersonIsStudentDriving() == 0 ) + continue; + + + // use a time UEC to get the od times for this person's location choice + boolean debugFlag = hhObj.getDebugChoiceModels(); + timeDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), person.getUsualSchoolLocation(), debugFlag ); + + double auto[] = timeUec[0].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double transit[] = timeUec[1].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double walk[] = timeUec[2].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + + // set the minimum of walk and transit time to walk time if no transit access, + // otherwise to the minimum of walk and transit time. + double minWalkTransit = walk[0]; + if ( transit[0] > 0 && transit[0] < walk[0] ) { + minWalkTransit = transit[0]; + } + + // set auto savings to be minimum of walk and transit time minus auto time + double autoSavings = minWalkTransit - auto[0]; + double autoSavingsRatio = ( autoSavings < 120 ? autoSavings/120.0 : 1.0 ); + + totalAutoSavingsRatio += autoSavingsRatio; + + } + + return totalAutoSavingsRatio; + + } + + + private double getSchoolNonDriveTourAutoTimeSavings( HouseholdIf hhObj ) { + + double totalAutoSavingsRatio = 0.0; + + TimeDMU timeDmuObject = new TimeDMU (); + int[] availability = new int[2]; + availability[1] = 1; + + // determine the travel time savings from home to chosen work and school locations + // for workers ans sr=tudents by student category + PersonIf[] personArray = hhObj.getPersons(); + for ( int i=1; i < personArray.length; i++ ) { + + PersonIf person = personArray[i]; + + + // if person is not a worker, skip to next person. + if ( person.getPersonIsStudentNonDriving() == 0 ) + continue; + + + // use a time UEC to get the od times for this person's location choice + boolean debugFlag = hhObj.getDebugChoiceModels(); + timeDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), person.getUsualSchoolLocation(), debugFlag ); + + double auto[] = timeUec[0].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double transit[] = timeUec[1].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + double walk[] = timeUec[2].solve( timeDmuObject.getDmuIndexValues(), timeDmuObject, availability ); + + // set the minimum of walk and transit time to walk time if no transit access, + // otherwise to the minimum of walk and transit time. + double minWalkTransit = walk[0]; + if ( transit[0] > 0 && transit[0] < walk[0] ) { + minWalkTransit = transit[0]; + } + + // set auto savings to be minimum of walk and transit time minus auto time + double autoSavings = minWalkTransit - auto[0]; + double autoSavingsRatio = ( autoSavings < 120 ? autoSavings/120.0 : 1.0 ); + + totalAutoSavingsRatio += autoSavingsRatio; + + } + + return totalAutoSavingsRatio; + + } + + private double getWorkAutoDependency(HouseholdIf hhObj) { + + PersonIf[] persons = hhObj.getPersons(); + + double hh_auto_depend = 0; + + //for all workers + for ( int i=1; i < persons.length; i++ ) { + + PersonIf p = persons[i]; + + if(p.getPersonIsWorker()==1) { + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hhObj ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( p.makeDefaultTour( modelStructure.getPrimaryPurposeIndex( ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase() ) ) ); + mcDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), p.getPersonWorkLocationZone(), hhObj.getDebugChoiceModels() ); + mcDmuObject.setTourOrigTaz( hhObj.getHhTaz() ); + mcDmuObject.setTourOrigWalkSubzone( hhObj.getHhWalkSubzone() ); + mcDmuObject.setTourDestTaz( p.getPersonWorkLocationZone() ); + mcDmuObject.setTourDestWalkSubzone( p.getPersonWorkLocationSubZone() ); + mcDmuObject.setTourDepartPeriod( modelStructure.getWorkLocationDefaultDepartPeriod() ); + mcDmuObject.setTourArrivePeriod( modelStructure.getWorkLocationDefaultArrivePeriod() ); + mcDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), p.getPersonWorkLocationZone(), hhObj.getDebugChoiceModels() ); + + //create TVPB for auto dependency model + setTVPBValues(mcDmuObject, ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase()); + + // get the choice model application + String choiceModelDescription = String.format ( "Auto Dependency Model for: Auto, primaryPurpose=%s, Orig=%d, OrigSubZ=%d, Dest=%d, DestSubZ=%d", + ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase(), hhObj.getHhTaz(), hhObj.getHhWalkSubzone(), p.getPersonWorkLocationZone(), p.getPersonWorkLocationSubZone() ); + String decisionMakerLabel = String.format ( "HH=%d", p.getHouseholdObject().getHhId()); + double auto = adModel.getLogsum(mcDmuObject, ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase(), logger, choiceModelDescription, decisionMakerLabel, true); + + choiceModelDescription = String.format ( "Auto Dependency Model for: Non-auto, primaryPurpose=%s, Orig=%d, OrigSubZ=%d, Dest=%d, DestSubZ=%d", + ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase(), hhObj.getHhTaz(), hhObj.getHhWalkSubzone(), p.getPersonWorkLocationZone(), p.getPersonWorkLocationSubZone() ); + double non_auto = adModel.getLogsum(mcDmuObject, ModelStructure.WORK_PRIMARY_PURPOSE_NAME.toLowerCase(), logger, choiceModelDescription, decisionMakerLabel, false); + + //adjust term + double person_auto_depend = Math.min(Math.max(auto - non_auto, 0) / 6, 1); + hh_auto_depend = hh_auto_depend + person_auto_depend; + } + } + + return hh_auto_depend; + + } + + private double getSchoolAutoDependency(HouseholdIf hhObj) { + + PersonIf[] persons = hhObj.getPersons(); + + double hh_auto_depend = 0; + + for ( int i=1; i < persons.length; i++ ) { + + PersonIf p = persons[i]; + + String tourPrimaryPurpose = ""; + int tourDepart = -1; + int tourArrive = -1; + + //for all ptype 3 (univ) and 6 (student 16+) + if(p.getPersonIsUniversityStudent()==1) { + tourPrimaryPurpose = ModelStructure.UNIVERSITY_PRIMARY_PURPOSE_NAME.toLowerCase(); + tourDepart = modelStructure.getUniversityLocationDefaultDepartPeriod(); + tourArrive = modelStructure.getUniversityLocationDefaultArrivePeriod(); + } else if ( p.getPersonIsStudentDriving()==1 ) { + tourPrimaryPurpose = ModelStructure.SCHOOL_PRIMARY_PURPOSE_NAME.toLowerCase(); + tourDepart = modelStructure.getSchoolLocationDefaultDepartPeriod(); + tourArrive = modelStructure.getSchoolLocationDefaultArrivePeriod(); + } else { + continue; + } + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hhObj ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( p.makeDefaultTour( modelStructure.getPrimaryPurposeIndex( tourPrimaryPurpose ) ) ); + mcDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), p.getPersonSchoolLocationZone(), hhObj.getDebugChoiceModels() ); + mcDmuObject.setTourOrigTaz( hhObj.getHhTaz() ); + mcDmuObject.setTourOrigWalkSubzone( hhObj.getHhWalkSubzone() ); + mcDmuObject.setTourDestTaz( p.getPersonSchoolLocationZone() ); + mcDmuObject.setTourDestWalkSubzone( p.getPersonSchoolLocationSubZone() ); + mcDmuObject.setTourDepartPeriod( tourDepart ); + mcDmuObject.setTourArrivePeriod( tourArrive ); + mcDmuObject.setDmuIndexValues( hhObj.getHhId(), hhObj.getHhTaz(), hhObj.getHhTaz(), p.getPersonSchoolLocationZone(), hhObj.getDebugChoiceModels() ); + + //create TVPB for auto dependency model + setTVPBValues(mcDmuObject, tourPrimaryPurpose); + + // get the choice model application + String choiceModelDescription = String.format ( "Auto Dependency Model for: Auto, primaryPurpose=%s, Orig=%d, OrigSubZ=%d, Dest=%d, DestSubZ=%d", + tourPrimaryPurpose, hhObj.getHhTaz(), hhObj.getHhWalkSubzone(), p.getPersonSchoolLocationZone(), p.getPersonSchoolLocationSubZone() ); + String decisionMakerLabel = String.format ( "HH=%d", p.getHouseholdObject().getHhId()); + double auto = adModel.getLogsum(mcDmuObject, tourPrimaryPurpose, logger, choiceModelDescription, decisionMakerLabel, true); + + choiceModelDescription = String.format ( "Auto Dependency Model for: Non-auto, primaryPurpose=%s, Orig=%d, OrigSubZ=%d, Dest=%d, DestSubZ=%d", + tourPrimaryPurpose, hhObj.getHhTaz(), hhObj.getHhWalkSubzone(), p.getPersonSchoolLocationZone(), p.getPersonSchoolLocationSubZone() ); + double non_auto = adModel.getLogsum(mcDmuObject, tourPrimaryPurpose, logger, choiceModelDescription, decisionMakerLabel, false); + + //adjust term + double person_auto_depend = Math.min(Math.max(auto - non_auto, 0) / 6, 1); + hh_auto_depend = hh_auto_depend + person_auto_depend; + } + + return hh_auto_depend; + } + + + public void setTVPBValues(TourModeChoiceDMU mcDmuObject, String purpose) { + + int NA_VALUE = 0; + + //use inbound dmu label (_In) for peak outbound + Trip trip = new Trip(); + trip.setTripid(mcDmuObject.getTourObject().getHhId()); + trip.setOtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getOriginZone())); + trip.setDtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getDestZone())); + trip.setOmaz(mcDmuObject.getDmuIndexValues().getOriginZone()); + trip.setDmaz(mcDmuObject.getDmuIndexValues().getDestZone()); + trip.setAge(mcDmuObject.getTourObject().getPersonObject().getAge()); + trip.setCars(mcDmuObject.getAutos()); + trip.setTod(mcDmuObject.getTodOut()); + trip.setHhincome(mcDmuObject.getHouseholdObject().getIncomeInDollars()); + trip.setInbound(0); + trip.setDebugRecord(mcDmuObject.getHouseholdObject().getDebugChoiceModels()); + + trip.setWalkTimeWeight(mcDmuObject.getTourObject().getPersonObject().getWalkTimeWeight()); + trip.setWalkSpeed(mcDmuObject.getTourObject().getPersonObject().getWalkSpeed()); + trip.setMaxWalk(mcDmuObject.getTourObject().getPersonObject().getMaxWalk()); + trip.setValueOfTime(mcDmuObject.getTourObject().getPersonObject().getValueOfTime()); + + trip.setPurpose(purpose.toLowerCase().startsWith("work") ? 1 : 0); + trip.setUserClassByType("user_class_work_walk", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_walk")); + trip.setUserClassByType("user_class_work_pnr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_pnr")); + trip.setUserClassByType("user_class_work_knr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_knr")); + trip.setUserClassByType("user_class_non_work_walk", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_walk")); + trip.setUserClassByType("user_class_non_work_pnr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_pnr")); + trip.setUserClassByType("user_class_non_work_knr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_knr")); + + tvpb.calculatePathsForATrip(trip, true, true, false); + + TapPair bestWalkTapPair; + TapPair bestPnrTapPair; + if(trip.getWalkTapPairs().size()>0) { + bestWalkTapPair = trip.getWalkTapPairs().get(0); //get best + mcDmuObject.setGenCostWT_In( (float) bestWalkTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapWT_In( bestWalkTapPair.otap ); + mcDmuObject.setDtapWT_In( bestWalkTapPair.dtap ); + } else { + mcDmuObject.setGenCostWT_In( NA_VALUE ); + mcDmuObject.setOtapWT_In( NA_VALUE ); + mcDmuObject.setDtapWT_In( NA_VALUE ); + } + + if(trip.getPnrTapPairs().size()>0) { + bestPnrTapPair = trip.getPnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDP_In( (float) bestPnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDP_In( bestPnrTapPair.otap ); + mcDmuObject.setDtapDP_In( bestPnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDP_In( NA_VALUE ); + mcDmuObject.setOtapDP_In( NA_VALUE ); + mcDmuObject.setDtapDP_In( NA_VALUE ); + } + + mcDmuObject.setGenCostDL_In( NA_VALUE ); + mcDmuObject.setOtapDL_In( NA_VALUE ); + mcDmuObject.setDtapDL_In( NA_VALUE ); + + //use outbound dmu label (_Out) for offpeak outbound + trip.setTod(modelStructure.getTod(modelStructure.getNonMandatoryLocationDefaultDepartPeriod())); + + tvpb.calculatePathsForATrip(trip, true, true, false); + + if(trip.getWalkTapPairs().size()>0) { + bestWalkTapPair = trip.getWalkTapPairs().get(0); //get best + mcDmuObject.setGenCostWT_Out( (float) bestWalkTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapWT_Out( bestWalkTapPair.otap ); + mcDmuObject.setDtapWT_Out( bestWalkTapPair.dtap ); + } else { + mcDmuObject.setGenCostWT_Out( NA_VALUE ); + mcDmuObject.setOtapWT_Out( NA_VALUE ); + mcDmuObject.setDtapWT_Out( NA_VALUE ); + } + + if(trip.getPnrTapPairs().size()>0) { + bestPnrTapPair = trip.getPnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDP_Out( (float) bestPnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDP_Out( bestPnrTapPair.otap ); + mcDmuObject.setDtapDP_Out( bestPnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDP_Out( NA_VALUE ); + mcDmuObject.setOtapDP_Out( NA_VALUE ); + mcDmuObject.setDtapDP_Out( NA_VALUE ); + } + + mcDmuObject.setGenCostDL_Out( NA_VALUE ); + mcDmuObject.setOtapDL_Out( NA_VALUE ); + mcDmuObject.setDtapDL_Out( NA_VALUE ); + + } +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelRunner.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelRunner.java new file mode 100644 index 0000000..40d3499 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelRunner.java @@ -0,0 +1,247 @@ +package com.pb.models.ctrampIf.jppf; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jppf.client.JPPFClient; +import org.jppf.client.JPPFJob; +import org.jppf.node.protocol.DataProvider; +import org.jppf.node.protocol.MemoryMapDataProvider; +import org.jppf.node.protocol.Task; + +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; + + +public class HouseholdChoiceModelRunner { + + private Logger logger = Logger.getLogger(HouseholdChoiceModelRunner.class); + + private static int PACKET_SIZE = 0; + + private static String PROPERTIES_NUM_INITIALIZATION_PACKETS = "number.initialization.packets"; + private static String PROPERTIES_INITIALIZATION_PACKET_SIZE = "initialization.packet.size"; + private static int NUM_INITIALIZATION_PACKETS = 0; + private static int INITIALIZATION_PACKET_SIZE = 0; + + private int ONE_HH_ID = -1; + + private static final String HOUSEHOLD_CHOICE_PACKET_SIZE = "distributed.task.packet.size"; + private static final String RUN_THIS_HOUSEHOLD_ONLY = "run.this.household.only"; + + private HashMap propertyMap; + private String restartModelString; + private MatrixDataServerIf ms; + private HouseholdDataManagerIf hhDataManager; + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + private CtrampDmuFactoryIf dmuFactory; + + private JPPFClient jppfClient = new JPPFClient(); + + + // The number of initialization packets are the number of "small" packets submited at the beginning of a + // distributed task to minimize synchronization issues that significantly slow down model object setup. + // It is assumed that after theses small packets have run, all the model objects will have been setup, + // and the task objects can process much bigger chuncks of households. + + + public HouseholdChoiceModelRunner( HashMap propertyMap, JPPFClient jppfClient, String restartModelString, HouseholdDataManagerIf hhDataManager, MatrixDataServerIf ms, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + setupHouseholdChoiceModelRunner ( propertyMap, jppfClient, restartModelString, hhDataManager, ms, modelStructure, tazDataManager, dmuFactory ); + } + + + private void setupHouseholdChoiceModelRunner ( HashMap propertyMap, JPPFClient jppfClient, String restartModelString, HouseholdDataManagerIf hhDataManager, MatrixDataServerIf ms, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + this.propertyMap = propertyMap; + this.restartModelString = restartModelString; + this.hhDataManager = hhDataManager; + this.ms = ms; + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + this.dmuFactory = dmuFactory; + this.jppfClient = jppfClient; + + + String oneHhString = propertyMap.get( RUN_THIS_HOUSEHOLD_ONLY ); + if ( oneHhString != null ) + ONE_HH_ID = Integer.parseInt( oneHhString ); + + + String propertyValue = propertyMap.get( HOUSEHOLD_CHOICE_PACKET_SIZE ); + if ( propertyValue == null ) + PACKET_SIZE = 0; + else + PACKET_SIZE = Integer.parseInt( propertyValue ); + + + propertyValue = propertyMap.get( PROPERTIES_NUM_INITIALIZATION_PACKETS ); + if ( propertyValue == null ) + NUM_INITIALIZATION_PACKETS = 0; + else + NUM_INITIALIZATION_PACKETS = Integer.parseInt( propertyValue ); + + + propertyValue = propertyMap.get( PROPERTIES_INITIALIZATION_PACKET_SIZE ); + if ( propertyValue == null ) + INITIALIZATION_PACKET_SIZE = 0; + else + INITIALIZATION_PACKET_SIZE = Integer.parseInt( propertyValue ); + + + } + + + + /** + * + * JPPF framework based method + */ + public void runHouseholdChoiceModels () { + + long initTime = System.currentTimeMillis(); + + submitTasks(); + + jppfClient.close(); + + logger.info( String.format( "household model runner finished %d households in %d minutes.", hhDataManager.getNumHouseholds(), ((System.currentTimeMillis()-initTime)/1000)/60 ) ); + + } + + + /** + * @param client is a JPPFClient object which is used to establish a connection to a computing node, submit tasks, and receive results. + */ + private void submitTasks() { + + // if PACKET_SIZE was not specified, create a single task to use for all households + if ( PACKET_SIZE == 0 ) + PACKET_SIZE = hhDataManager.getNumHouseholds(); + + + // Create a setup task object and submit it to the computing node. + // This setup task creates the HouseholdChoiceModelManager and causes it to create the necessary numuber + // of HouseholdChoiceModels objects which will operate in parallel on the computing node. + try { + + JPPFJob job = new JPPFJob(); + + DataProvider dataProvider = new MemoryMapDataProvider(); + dataProvider.setParameter("propertyMap", propertyMap); + dataProvider.setParameter("ms", ms); + dataProvider.setParameter("modelStructure", modelStructure); + dataProvider.setParameter("tazDataManager", tazDataManager); + dataProvider.setParameter("householdDataManager", hhDataManager); + dataProvider.setParameter("dmuFactory", dmuFactory); + dataProvider.setParameter("restartModelString", restartModelString); + + job.setDataProvider(dataProvider); + + ArrayList startEndTaskIndicesList = getTaskHouseholdRanges( hhDataManager.getNumHouseholds() ); + + int startIndex = 0; + int endIndex = 0; + int taskIndex = 1; + for ( int[] startEndIndices : startEndTaskIndicesList ) { + startIndex = startEndIndices[0]; + endIndex = startEndIndices[1]; + + HouseholdChoiceModelsTaskJppf task = new HouseholdChoiceModelsTaskJppf( taskIndex, startIndex, endIndex ); + job.add ( task ); + taskIndex++; + } + + + + List> results = jppfClient.submitJob(job); + for (Task task : results) { + if (task.getException() != null) throw task.getException(); + + try { + logger.info( String.format("HH TASK: %s returned: %s.", task.getId(), (String)task.getResult() ) ); + } + catch (Exception e) { + logger.error( "Exception returned by computing node caught in HouseholdChoiceModelsTaskJppf.", e ); + throw new RuntimeException(); + } + + } + + } + catch (Exception e) { + logger.error( "Exception caught creating/submitting/receiving HouseholdChoiceModelsTaskJppf.", e ); + throw new RuntimeException(); + } + + } + + + + private ArrayList getTaskHouseholdRanges( int numberOfHouseholds ) { + + ArrayList startEndIndexList = new ArrayList(); + + if ( ONE_HH_ID < 0 ) { + + int numInitializationHouseholds = NUM_INITIALIZATION_PACKETS*INITIALIZATION_PACKET_SIZE; + + + int startIndex = 0; + int endIndex = 0; + if ( numInitializationHouseholds < numberOfHouseholds ) { + + while ( endIndex < numInitializationHouseholds ) { + endIndex = startIndex + INITIALIZATION_PACKET_SIZE - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += INITIALIZATION_PACKET_SIZE; + } + + } + + + while ( endIndex < numberOfHouseholds - 1 ) { + endIndex = startIndex + PACKET_SIZE - 1; + if ( endIndex + PACKET_SIZE > numberOfHouseholds ) + endIndex = numberOfHouseholds - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += PACKET_SIZE; + } + + + return startEndIndexList; + + } + else { + + // create a single task packet high one household id + int[] startEndIndices = new int[2]; + int index = hhDataManager.getArrayIndex( ONE_HH_ID ); + startEndIndices[0] = index; + startEndIndices[1] = index; + startEndIndexList.add( startEndIndices ); + + return startEndIndexList; + + } + + + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModels.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModels.java new file mode 100644 index 0000000..e1a45c1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModels.java @@ -0,0 +1,642 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import com.pb.common.util.ObjectUtil; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; + + + +public class HouseholdChoiceModels implements Serializable { + + private transient Logger logger = Logger.getLogger("HouseholdChoiceModels"); + + private boolean runAutoOwnershipModel; + private boolean runFreeParkingAvailableModel; + private boolean runCoordinatedDailyActivityPatternModel; + private boolean runIndividualMandatoryTourFrequencyModel; + private boolean runMandatoryTourModeChoiceModel; + private boolean runMandatoryTourDepartureTimeAndDurationModel; + private boolean runAtWorkSubtourFrequencyModel; + private boolean runAtWorkSubtourLocationChoiceModel; + private boolean runAtWorkSubtourModeChoiceModel; + private boolean runAtWorkSubtourDepartureTimeAndDurationModel; + private boolean runJointTourFrequencyModel; + private boolean runJointTourLocationChoiceModel; + private boolean runJointTourDepartureTimeAndDurationModel; + private boolean runJointTourModeChoiceModel; + private boolean runIndividualNonMandatoryTourFrequencyModel; + private boolean runIndividualNonMandatoryTourLocationChoiceModel; + private boolean runIndividualNonMandatoryTourModeChoiceModel; + private boolean runIndividualNonMandatoryTourDepartureTimeAndDurationModel; + private boolean runStopFrequencyModel; + private boolean runStopLocationModel; + + private String restartModelString; + + private HouseholdAutoOwnershipModel aoModel; + private HouseholdFreeParkingModel fpModel; + private HouseholdCoordinatedDailyActivityPatternModel cdapModel; + private HouseholdIndividualMandatoryTourFrequencyModel imtfModel; + private ModeChoiceModel immcModel; + private HouseholdIndividualMandatoryTourDepartureAndDurationTime imtodModel; + private JointTourModels jtfModel; + private ModeChoiceModel jmcModel; + private HouseholdJointDestChoiceModel jlcModel; + private NonMandatoryTourDepartureAndDurationTime jTodModel; + private HouseholdIndividualNonMandatoryTourFrequencyModel inmtfModel; + private ModeChoiceModel inmmcModel; + private HouseholdIndNonManDestChoiceModel inmlcModel; + private NonMandatoryTourDepartureAndDurationTime inmTodModel; + private HouseholdAtWorkSubtourFrequencyModel awfModel; + private ModeChoiceModel awmcModel; + private HouseholdSubTourDestChoiceModel awlcModel; + private HouseholdAtWorkSubtourDepartureAndDurationTime awtodModel; + private StopFrequencyModel stfModel; + private StopLocationModeChoiceModel stlmcModel; + + private long aoTime; + private long fpTime; + private long cdapTime; + private long imtfTime; + private long imtodTime; + private long imtmcTime; + private long jtfTime; + private long jtdcTime; + private long jtodTime; + private long jtmcTime; + private long inmtfTime; + private long inmtdcTime; + private long inmtodTime; + private long inmtmcTime; + private long awtfTime; + private long awtdcTime; + private long awtodTime; + private long awtmcTime; + private long stfTime; + private long stdtmTime; + private long[] returnPartialTimes = new long[StopLocationModeChoiceModel.NUM_CPU_TIME_VALUES]; + + private int modelIndex; + + + + + public HouseholdChoiceModels( int modelIndex, String restartModelString, HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + this.modelIndex = modelIndex; + this.restartModelString = restartModelString; + + + try { + setupModels( propertyMap, tazDataManager, modelStructure, dmuFactory ); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + private void setupModels( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) throws IOException { + + runAutoOwnershipModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_AUTO_OWNERSHIP ) ); + runFreeParkingAvailableModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_FREE_PARKING_AVAILABLE ) ); + runCoordinatedDailyActivityPatternModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_DAILY_ACTIVITY_PATTERN ) ); + + runIndividualMandatoryTourFrequencyModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_INDIV_MANDATORY_TOUR_FREQ ) ); + runMandatoryTourDepartureTimeAndDurationModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_MAND_TOUR_DEP_TIME_AND_DUR ) ); + runMandatoryTourModeChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_MAND_TOUR_MODE_CHOICE ) ); + + runAtWorkSubtourFrequencyModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_AT_WORK_SUBTOUR_FREQ ) ); + runAtWorkSubtourLocationChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_AT_WORK_SUBTOUR_LOCATION_CHOICE ) ); + runAtWorkSubtourDepartureTimeAndDurationModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_AT_WORK_SUBTOUR_DEP_TIME_AND_DUR ) ); + runAtWorkSubtourModeChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_AT_WORK_SUBTOUR_MODE_CHOICE ) ); + + runJointTourFrequencyModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_JOINT_TOUR_FREQ ) ); + runJointTourLocationChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_JOINT_LOCATION_CHOICE ) ); + runJointTourDepartureTimeAndDurationModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_JOINT_TOUR_DEP_TIME_AND_DUR ) ); + runJointTourModeChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_JOINT_TOUR_MODE_CHOICE ) ); + + runIndividualNonMandatoryTourFrequencyModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_FREQ ) ); + runIndividualNonMandatoryTourLocationChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_INDIV_NON_MANDATORY_LOCATION_CHOICE ) ); + runIndividualNonMandatoryTourDepartureTimeAndDurationModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_DEP_TIME_AND_DUR ) ); + runIndividualNonMandatoryTourModeChoiceModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_INDIV_NON_MANDATORY_TOUR_MODE_CHOICE ) ); + + runStopFrequencyModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_STOP_FREQUENCY ) ); + runStopLocationModel = Boolean.parseBoolean( propertyMap.get( CtrampApplication.PROPERTIES_RUN_STOP_LOCATION ) ); + + checkModelRunFlags(); + + boolean measureObjectSizes = false; + + try { + + // create the auto ownership choice model application object + if ( runAutoOwnershipModel ) { + aoModel = new HouseholdAutoOwnershipModel( propertyMap, dmuFactory, tazDataManager, modelStructure ); + if ( measureObjectSizes ) logger.info ( "AO size: " + ObjectUtil.checkObjectSize( aoModel ) ); + } + + if ( runFreeParkingAvailableModel ) { + fpModel = new HouseholdFreeParkingModel( propertyMap, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "FP size: " + ObjectUtil.checkObjectSize( fpModel ) ); + } + + if ( runCoordinatedDailyActivityPatternModel ) { + cdapModel = new HouseholdCoordinatedDailyActivityPatternModel( propertyMap, modelStructure, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "CDAP size: " + ObjectUtil.checkObjectSize( cdapModel ) ); + } + + + if ( runIndividualMandatoryTourFrequencyModel ) { + imtfModel = new HouseholdIndividualMandatoryTourFrequencyModel( propertyMap, tazDataManager, modelStructure, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "IMTF size: " + ObjectUtil.checkObjectSize( imtfModel ) ); + } + + if ( runMandatoryTourModeChoiceModel || runMandatoryTourDepartureTimeAndDurationModel ){ + immcModel = new ModeChoiceModel( propertyMap, modelStructure, ModelStructure.MANDATORY_CATEGORY, dmuFactory,tazDataManager); + if ( measureObjectSizes ) logger.info ( "IMMC size: " + ObjectUtil.checkObjectSize( immcModel ) ); + } + + if ( runMandatoryTourDepartureTimeAndDurationModel ){ + imtodModel = new HouseholdIndividualMandatoryTourDepartureAndDurationTime( propertyMap, tazDataManager, modelStructure, dmuFactory, immcModel ); + if ( measureObjectSizes ) logger.info ( "IMTOD size: " + ObjectUtil.checkObjectSize( imtodModel ) ); + } + + + if ( runJointTourFrequencyModel ){ + jtfModel = new JointTourModels( propertyMap, modelStructure, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "JTF size: " + ObjectUtil.checkObjectSize( jtfModel ) ); + } + + if ( runJointTourModeChoiceModel || runJointTourLocationChoiceModel || runJointTourDepartureTimeAndDurationModel ){ + jmcModel = new ModeChoiceModel( propertyMap, modelStructure, ModelStructure.JOINT_NON_MANDATORY_CATEGORY, dmuFactory, tazDataManager); + if ( measureObjectSizes ) logger.info ( "JMC size: " + ObjectUtil.checkObjectSize( jmcModel ) ); + } + if ( runJointTourLocationChoiceModel ){ + //jlcModel = new HouseholdJointDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, jmcModel, jointProbabilitiesCache, jointCumProbabilitiesCache ); + jlcModel = new HouseholdJointDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, jmcModel ); + if ( measureObjectSizes ) logger.info ( "JLC size: " + ObjectUtil.checkObjectSize( jlcModel ) ); + } + if ( runJointTourDepartureTimeAndDurationModel ){ + jTodModel = new NonMandatoryTourDepartureAndDurationTime( propertyMap, modelStructure, dmuFactory, ModelStructure.JOINT_NON_MANDATORY_CATEGORY, jmcModel ); + if ( measureObjectSizes ) logger.info ( "JTOD size: " + ObjectUtil.checkObjectSize( jTodModel ) ); + } + + + if ( runIndividualNonMandatoryTourFrequencyModel ){ + inmtfModel = new HouseholdIndividualNonMandatoryTourFrequencyModel( propertyMap, modelStructure, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "INMTF size: " + ObjectUtil.checkObjectSize( inmtfModel ) ); + } + if ( runIndividualNonMandatoryTourModeChoiceModel || runIndividualNonMandatoryTourLocationChoiceModel || runIndividualNonMandatoryTourDepartureTimeAndDurationModel){ + inmmcModel = new ModeChoiceModel( propertyMap, modelStructure, ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY, dmuFactory, tazDataManager); + if ( measureObjectSizes ) logger.info ( "INMMC size: " + ObjectUtil.checkObjectSize( inmmcModel ) ); + } + if ( runIndividualNonMandatoryTourLocationChoiceModel ){ + //inmlcModel = new HouseholdIndNonManDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, inmmcModel, indivNonManProbabilitiesCache, indivNonManCumProbabilitiesCache ); + inmlcModel = new HouseholdIndNonManDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, inmmcModel ); + if ( measureObjectSizes ) logger.info ( "INMLC size: " + ObjectUtil.checkObjectSize( inmlcModel ) ); + } + if ( runIndividualNonMandatoryTourDepartureTimeAndDurationModel ){ + inmTodModel = new NonMandatoryTourDepartureAndDurationTime( propertyMap, modelStructure, dmuFactory, ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY, inmmcModel ); + if ( measureObjectSizes ) logger.info ( "INMTOD size: " + ObjectUtil.checkObjectSize( inmTodModel ) ); + } + + + if ( runAtWorkSubtourFrequencyModel ){ + awfModel = new HouseholdAtWorkSubtourFrequencyModel( propertyMap, modelStructure, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "AWF size: " + ObjectUtil.checkObjectSize( awfModel ) ); + } + if ( runAtWorkSubtourModeChoiceModel || runAtWorkSubtourLocationChoiceModel || runAtWorkSubtourDepartureTimeAndDurationModel ){ + awmcModel = new ModeChoiceModel( propertyMap, modelStructure, ModelStructure.AT_WORK_CATEGORY, dmuFactory, tazDataManager); + if ( measureObjectSizes ) logger.info ( "AWMC size: " + ObjectUtil.checkObjectSize( awmcModel ) ); + } + if ( runAtWorkSubtourLocationChoiceModel ){ + //awlcModel = new HouseholdSubTourDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, awmcModel, atWorkProbabilitiesCache, atWorkCumProbabilitiesCache ); + awlcModel = new HouseholdSubTourDestChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory, awmcModel ); + if ( measureObjectSizes ) logger.info ( "AWLC size: " + ObjectUtil.checkObjectSize( awlcModel ) ); + } + if ( runAtWorkSubtourDepartureTimeAndDurationModel ){ + awtodModel = new HouseholdAtWorkSubtourDepartureAndDurationTime( propertyMap, modelStructure, tazDataManager, dmuFactory, awmcModel ); + if ( measureObjectSizes ) logger.info ( "AWTOD size: " + ObjectUtil.checkObjectSize( awtodModel ) ); + } + + + if ( runStopFrequencyModel ){ + stfModel = new StopFrequencyModel( propertyMap, modelStructure, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "STF size: " + ObjectUtil.checkObjectSize( stfModel ) ); + } + + if ( runStopLocationModel ){ + stlmcModel = new StopLocationModeChoiceModel( propertyMap, modelStructure, tazDataManager, dmuFactory ); + if ( measureObjectSizes ) logger.info ( "STLMC size: " + ObjectUtil.checkObjectSize( stlmcModel ) ); + } + + } + catch ( RuntimeException e ) { + + String lastModel = ""; + if ( runAutoOwnershipModel && aoModel != null ) + lastModel += " ao"; + + if ( runFreeParkingAvailableModel && fpModel != null ) + lastModel += " fp"; + + if ( runCoordinatedDailyActivityPatternModel && cdapModel != null ) + lastModel += " cdap"; + + if ( runIndividualMandatoryTourFrequencyModel && imtfModel != null ) + lastModel += " imtf"; + + if ( runMandatoryTourDepartureTimeAndDurationModel && imtodModel != null ) + lastModel += " imtod"; + + if ( runMandatoryTourModeChoiceModel && immcModel != null ) + lastModel += " immc"; + + if ( runJointTourFrequencyModel && jtfModel != null ) + lastModel += " jtf"; + + if ( runJointTourLocationChoiceModel && jlcModel != null ) + lastModel += " jlc"; + + if ( runJointTourDepartureTimeAndDurationModel && jTodModel != null ) + lastModel += " jtod"; + + if ( runJointTourModeChoiceModel && jmcModel != null ) + lastModel += " jmc"; + + if ( runIndividualNonMandatoryTourFrequencyModel && inmtfModel != null ) + lastModel += " inmtf"; + + if ( runIndividualNonMandatoryTourLocationChoiceModel && inmlcModel != null ) + lastModel += " inmlc"; + + if ( runIndividualNonMandatoryTourDepartureTimeAndDurationModel && inmTodModel != null ) + lastModel += " inmtod"; + + if ( runIndividualNonMandatoryTourModeChoiceModel && inmmcModel != null ) + lastModel += " inmmc"; + + if ( runAtWorkSubtourFrequencyModel && awfModel != null ) + lastModel += " awf"; + + if ( runAtWorkSubtourLocationChoiceModel && awlcModel != null ) + lastModel += " awlc"; + + if ( runAtWorkSubtourDepartureTimeAndDurationModel && awtodModel != null ) + lastModel += " awtod"; + + if ( runAtWorkSubtourModeChoiceModel && awmcModel != null ) + lastModel += " awmc"; + + if ( runStopFrequencyModel && stfModel != null ) + lastModel += " stf"; + + if ( runStopLocationModel && stlmcModel != null ) + lastModel += " stlmc"; + + logger.error( "RuntimeException setting up HouseholdChoiceModels." ); + logger.error( "Models setup = " + lastModel ); + logger.error( "", e ); + + throw e; + } + + + } + + + public void cleanUp() { + + if ( stlmcModel != null ) + stlmcModel.cleanUp(); + } + + + public void zeroTimes() { + aoTime = 0; + fpTime = 0; + cdapTime = 0; + imtfTime = 0; + imtodTime = 0; + imtmcTime = 0; + jtfTime = 0; + jtdcTime = 0; + jtodTime = 0; + jtmcTime = 0; + inmtfTime = 0; + inmtdcTime = 0; + inmtodTime = 0; + inmtmcTime = 0; + awtfTime = 0; + awtdcTime = 0; + awtodTime = 0; + awtmcTime = 0; + stfTime = 0; + stdtmTime = 0; + + Arrays.fill( returnPartialTimes, 0 ); + } + + + public long[] getPartialStopTimes() { + return returnPartialTimes; + } + + public long[] getTimes() { + long[] returnTimes = new long[20]; + returnTimes[0] = aoTime; + returnTimes[1] = fpTime; + returnTimes[2] = cdapTime; + returnTimes[3] = imtfTime; + returnTimes[4] = imtodTime; + returnTimes[5] = imtmcTime; + returnTimes[6] = jtfTime; + returnTimes[7] = jtdcTime; + returnTimes[8] = jtodTime; + returnTimes[9] = jtmcTime; + returnTimes[10] = inmtfTime; + returnTimes[11] = inmtdcTime; + returnTimes[12] = inmtodTime; + returnTimes[13] = inmtmcTime; + returnTimes[14] = awtfTime; + returnTimes[15] = awtdcTime; + returnTimes[16] = awtodTime; + returnTimes[17] = awtmcTime; + returnTimes[18] = stfTime; + returnTimes[19] = stdtmTime; + return returnTimes; + } + + + public void runModels( HouseholdIf hhObject ) { + + + // check to see if restartModel was set and reset random number sequence appropriately if so. + checkRestartModel( hhObject ); + + if ( runAutoOwnershipModel ) + aoModel.applyModel( hhObject ); + + if ( runFreeParkingAvailableModel ) + fpModel.applyModel( hhObject ); + + if ( runCoordinatedDailyActivityPatternModel ) + cdapModel.applyModel( hhObject ); + + if ( runIndividualMandatoryTourFrequencyModel ) + imtfModel.applyModel( hhObject ); + + if ( runMandatoryTourDepartureTimeAndDurationModel ) + imtodModel.applyModel( hhObject, runMandatoryTourModeChoiceModel ); + + if ( runJointTourFrequencyModel ) + jtfModel.applyModel( hhObject ); + + if ( runJointTourLocationChoiceModel ) + jlcModel.applyModel( hhObject ); + + if ( runJointTourDepartureTimeAndDurationModel ) + jTodModel.applyJointModel( hhObject, runJointTourModeChoiceModel ); + + if ( runIndividualNonMandatoryTourFrequencyModel ) + inmtfModel.applyModel( hhObject ); + + if ( runIndividualNonMandatoryTourLocationChoiceModel ) + inmlcModel.applyModel( hhObject ); + + if ( runIndividualNonMandatoryTourDepartureTimeAndDurationModel ) + inmTodModel.applyIndivModel( hhObject, runIndividualNonMandatoryTourModeChoiceModel ); + + if ( runAtWorkSubtourFrequencyModel ) + awfModel.applyModel( hhObject ); + + if ( runAtWorkSubtourLocationChoiceModel ) + awlcModel.applyModel( hhObject ); + + if ( runAtWorkSubtourDepartureTimeAndDurationModel ) + awtodModel.applyModel( hhObject, runAtWorkSubtourModeChoiceModel ); + + if ( runStopFrequencyModel ) + stfModel.applyModel( hhObject ); + + if ( runStopLocationModel ) + stlmcModel.applyModel( hhObject ); + + + //} + + } + + + public void runModelsWithTiming( HouseholdIf hhObject ) { + + // check to see if restartModel was set and reset random number sequence appropriately if so. + checkRestartModel( hhObject ); + + if ( runAutoOwnershipModel ) { + long check = System.nanoTime(); + aoModel.applyModel( hhObject ); + aoTime += ( System.nanoTime() - check ); + } + + if ( runFreeParkingAvailableModel ) { + long check = System.nanoTime(); + fpModel.applyModel( hhObject ); + fpTime += ( System.nanoTime() - check ); + } + + if ( runCoordinatedDailyActivityPatternModel ) { + long check = System.nanoTime(); + cdapModel.applyModel( hhObject ); + cdapTime += ( System.nanoTime() - check ); + } + + if ( runIndividualMandatoryTourFrequencyModel ) { + long check = System.nanoTime(); + imtfModel.applyModel( hhObject ); + imtfTime += ( System.nanoTime() - check ); + } + + if ( runMandatoryTourDepartureTimeAndDurationModel ) { + long check = System.nanoTime(); + imtodModel.applyModel( hhObject, runMandatoryTourModeChoiceModel ); + imtodTime += ( System.nanoTime() - check ); + } + + if ( runJointTourFrequencyModel ) { + long check = System.nanoTime(); + jtfModel.applyModel( hhObject ); + jtfTime += ( System.nanoTime() - check ); + } + + if ( runJointTourLocationChoiceModel ) { + long check = System.nanoTime(); + jlcModel.applyModel( hhObject ); + jtdcTime += ( System.nanoTime() - check ); + } + + if ( runJointTourDepartureTimeAndDurationModel ) { + long check = System.nanoTime(); + jTodModel.applyJointModel( hhObject, runJointTourModeChoiceModel ); + jtodTime += ( System.nanoTime() - check ); + } + + if ( runIndividualNonMandatoryTourFrequencyModel ) { + long check = System.nanoTime(); + inmtfModel.applyModel( hhObject ); + inmtfTime += ( System.nanoTime() - check ); + } + + if ( runIndividualNonMandatoryTourLocationChoiceModel ) { + long check = System.nanoTime(); + inmlcModel.applyModel( hhObject ); + inmtdcTime += ( System.nanoTime() - check ); + } + + if ( runIndividualNonMandatoryTourDepartureTimeAndDurationModel ) { + long check = System.nanoTime(); + inmTodModel.applyIndivModel( hhObject, runIndividualNonMandatoryTourModeChoiceModel ); + inmtodTime += ( System.nanoTime() - check ); + } + + if ( runAtWorkSubtourFrequencyModel ) { + long check = System.nanoTime(); + awfModel.applyModel( hhObject ); + awtfTime += ( System.nanoTime() - check ); + } + + if ( runAtWorkSubtourLocationChoiceModel ) { + long check = System.nanoTime(); + awlcModel.applyModel( hhObject ); + awtdcTime += ( System.nanoTime() - check ); + } + + if ( runAtWorkSubtourDepartureTimeAndDurationModel ) { + long check = System.nanoTime(); + awtodModel.applyModel( hhObject, runAtWorkSubtourModeChoiceModel ); + awtodTime += ( System.nanoTime() - check ); + } + + if ( runStopFrequencyModel ) { + long check = System.nanoTime(); + stfModel.applyModel( hhObject ); + stfTime += ( System.nanoTime() - check ); + } + + if ( runStopLocationModel ) { + long check = System.nanoTime(); + stlmcModel.applyModel( hhObject ); + stdtmTime += ( System.nanoTime() - check ); + + long[] partials = stlmcModel.getStopTimes(); + for ( int i=0; i < returnPartialTimes.length; i++ ) + returnPartialTimes[i] += partials[i]; + } + + + //} + + } + + + private void checkRestartModel( HouseholdIf hhObject ) { + + // version 1.0.8.22 - changed model restart options - possible values for restart are now: none, ao, imtf, immc, jtf, jmc, inmtf, inmmc, awf, awmc, stf + + + // if restartModel was specified, reset the random number sequence + // based on the cumulative count of random numbers drawn by the component preceding the one specified. + if ( restartModelString.equalsIgnoreCase("") || restartModelString.equalsIgnoreCase("none") ) + return; + else if ( restartModelString.equalsIgnoreCase("ao")) { + hhObject.initializeForAoRestart(); + } + else if ( restartModelString.equalsIgnoreCase("imtf")) { + hhObject.initializeForImtfRestart(); + } + else if ( restartModelString.equalsIgnoreCase("jtf")) { + hhObject.initializeForJtfRestart(); + } + else if ( restartModelString.equalsIgnoreCase("inmtf")) { + hhObject.initializeForInmtfRestart(); + } + else if ( restartModelString.equalsIgnoreCase("awf")) { + hhObject.initializeForAwfRestart(); + } + else if ( restartModelString.equalsIgnoreCase("stf")) { + hhObject.initializeForStfRestart(); + } + else { + throw new RuntimeException("Cannot restart model from " + restartModelString + ". Must be one of: none, ao, imtf, jtf, inmtf, awf, stf."); + } + + } + + private void checkModelRunFlags() { + + if (runMandatoryTourDepartureTimeAndDurationModel) { + if (!runIndividualMandatoryTourFrequencyModel) { + throw new RuntimeException("If running runMandatoryTourDepartureTimeAndDurationModel, runIndividualMandatoryTourFrequencyModel must also be true."); + } + } + + if (runJointTourDepartureTimeAndDurationModel) { + if (!runJointTourFrequencyModel) { + throw new RuntimeException("If running jointTourDepartureTimeAndDurationModel, jointTourFrequencyModel must also be true."); + } + if (!runJointTourLocationChoiceModel) { + throw new RuntimeException("If running jointTourDepartureTimeAndDurationModel, jointTourLocationModel must also be true."); + } + } + + if (runJointTourLocationChoiceModel) { + if (!runJointTourFrequencyModel) { + throw new RuntimeException("If running jointTourLocationChoiceModel, jointTourFrequencyModel must also be true."); + } + } + + if (runIndividualNonMandatoryTourDepartureTimeAndDurationModel) { + if (!runIndividualNonMandatoryTourFrequencyModel) { + throw new RuntimeException("If running individualNonMandatoryTourDepartureTimeAndDurationModel, individualNonMandatoryTourFrequencyModel must also be true."); + } + if (!runIndividualNonMandatoryTourLocationChoiceModel) { + throw new RuntimeException("If running individualNonMandatoryTourDepartureTimeAndDurationModel, individualNonMandatoryTourLocationModel must also be true."); + } + } + + if (runIndividualNonMandatoryTourLocationChoiceModel) { + if (!runIndividualNonMandatoryTourFrequencyModel) { + throw new RuntimeException("If running individualNonMandatoryLocationChoiceModel, individualNonMandatoryTourFrequencyModel must also be true."); + } + } + + if (runAtWorkSubtourDepartureTimeAndDurationModel) { + if (!runAtWorkSubtourFrequencyModel) { + throw new RuntimeException("If running atWorkSubtourDepartureTimeAndDurationModel, atWorkSubtourFrequencyModel must also be true."); + } + if (!runAtWorkSubtourLocationChoiceModel) { + throw new RuntimeException("If running atWorkSubtourDepartureTimeAndDurationModel, atWorkSubtourLocationModel must also be true."); + } + } + + if (runAtWorkSubtourLocationChoiceModel) { + if (!runAtWorkSubtourFrequencyModel) { + throw new RuntimeException("If running atWorkSubtourLocationChoiceModel, atWorkSubtourFrequencyModel must also be true."); + } + } + } + + public int getModelIndex(){ + return modelIndex; + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsManager.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsManager.java new file mode 100644 index 0000000..09ca5dc --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsManager.java @@ -0,0 +1,177 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.MatrixDataManager; +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.common.util.ObjectUtil; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; + +public class HouseholdChoiceModelsManager implements Serializable { + + private Logger logger = Logger.getLogger("HouseholdChoiceModelsManager"); + + private static HouseholdChoiceModelsManager objInstance = null; + + private LinkedList modelQueue = null; + + private HashMap propertyMap; + private String restartModelString; + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + private CtrampDmuFactoryIf dmuFactory; + + private int completedHouseholds = 0; + + private int modelIndex; + + + private HouseholdChoiceModelsManager(){ + } + + + + public static synchronized HouseholdChoiceModelsManager getInstance( HashMap propertyMap, String restartModelString, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + if ( objInstance == null ) { + objInstance = new HouseholdChoiceModelsManager(); + + objInstance.propertyMap = propertyMap; + objInstance.restartModelString = restartModelString; + objInstance.modelStructure = modelStructure; + objInstance.tazDataManager = tazDataManager; + objInstance.dmuFactory = dmuFactory; + + objInstance.completedHouseholds = 0; + objInstance.modelIndex = 0; + return objInstance; + } + else { + return objInstance; + } + } + + + // the task instances should call needToInitialize() first, then this method if necessary. + public synchronized void managerSetup( MatrixDataServerIf ms ) { + + if ( modelQueue != null ) + return; + + modelIndex = 0; + completedHouseholds = 0; + + //setupJointProbabilitiesCache(); + //setupIndivNonManProbabilitiesCache(); + //setupAtWorkProbabilitiesCache(); + + // get the factory object used to create and recycle dcModel objects. Call the manager's method to clear dcModel objects to free up memory if necessary. + DestChoiceModelManager dcModelManager = DestChoiceModelManager.getInstance(); + dcModelManager.clearDcModels(); + MatrixDataManager mdm = dcModelManager.getMatrixDataManager(); + + // the first thread to reach this method initializes the MatrixDataManager to use the MatrixDataServer instance passed in. + if ( ms == null ) { + if ( mdm != null ) { + logger.info ( Thread.currentThread().getName() + ": No remote MatrixServer being used, but MatrixDataManager already exists." ); + } + else { + logger.info ( Thread.currentThread().getName() + ": No remote MatrixServer being used, MatrixDataManager will get created when needed for HouseholdChoiceModelManager." ); + } + } + else if ( mdm == null ) { + String testString = ms.testRemote(); + logger.info ( String.format( Thread.currentThread().getName() + ": HouseholdChoiceModelManager needs MatrixDataManager, MatrixDataServer connection test: %s", testString ) ); + mdm = MatrixDataManager.getInstance(); + mdm.setMatrixDataServerObject( ms ); + } + else { + logger.info ( Thread.currentThread().getName() + ": MatrixDataManager already exists." ); + } + + // the first thread to reach this method initializes the modelQueue used to recycle hhChoiceModels objects. + modelQueue = new LinkedList(); + + } + + + /** + * @return DestChoiceModel object created if none is available from the queue. + * + */ + public synchronized HouseholdChoiceModels getHouseholdChoiceModelsObject( int taskIndex ) { + + String message = ""; + HouseholdChoiceModels hhChoiceModels = null; + + + if ( modelQueue.isEmpty() ) { + // create choice model object + //hhChoiceModels = new HouseholdChoiceModels( ++modelIndex, restartModelString, propertyMap, tazDataManager, modelStructure, dmuFactory, jointProbabilitiesCache, jointCumProbabilitiesCache, indivNonManProbabilitiesCache, indivNonManCumProbabilitiesCache, atWorkProbabilitiesCache, atWorkCumProbabilitiesCache ); + hhChoiceModels = new HouseholdChoiceModels( ++modelIndex, restartModelString, propertyMap, tazDataManager, modelStructure, dmuFactory ); + long size = 0; +// size = ObjectUtil.sizeOf( hhChoiceModels ); +// try { +// size = ObjectUtil.checkObjectSize( hhChoiceModels ); +// } +// catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + message = String.format( "created hhChoiceModels=%d, task=%d, thread=%s, size=%d MB.", modelIndex, taskIndex, Thread.currentThread().getName(), (size/(1024*1024)) ); + } + else { + hhChoiceModels = modelQueue.remove(); + message = String.format( "removed hhChoiceModels=%d from queue, task=%d, thread=%s.", hhChoiceModels.getModelIndex(), taskIndex, Thread.currentThread().getName() ); + } + logger.info( message ); + + return hhChoiceModels; + + } + + + /** + * return the HouseholdChoiceModels object to the manager's queue so that it may be used by another thread + * without it having to create one. + * @param hhModels + */ + public void returnHouseholdChoiceModelsObject ( HouseholdChoiceModels hhModels, int startIndex, int endIndex ) { + modelQueue.add( hhModels ); + completedHouseholds += (endIndex - startIndex + 1); + logger.info( "returned hhChoiceModels=" + hhModels.getModelIndex() + " to queue: thread=" + Thread.currentThread().getName() + ", completedHouseholds=" + completedHouseholds + "." ); + } + + + + + public synchronized void clearHhModels() { + + if ( modelQueue == null ) { + return; + } + + System.out.println( String.format( "%s: clearing household choice models modelQueue, thread=%s.", new Date(), Thread.currentThread().getName() ) ); + + while ( ! modelQueue.isEmpty() ) { + HouseholdChoiceModels hhChoiceModels = modelQueue.remove(); + hhChoiceModels.cleanUp(); + System.out.println( "cleaned up hhModel " + hhChoiceModels.getModelIndex() + "." ); + hhChoiceModels = null; + } + + modelIndex = 0; + completedHouseholds = 0; + + modelQueue = null; + + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsTaskJppf.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsTaskJppf.java new file mode 100644 index 0000000..172d151 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdChoiceModelsTaskJppf.java @@ -0,0 +1,172 @@ +package com.pb.models.ctrampIf.jppf; + +import java.net.UnknownHostException; +import java.util.HashMap; + +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; + +import org.apache.log4j.Logger; +import org.jppf.node.protocol.DataProvider; +import org.jppf.node.protocol.AbstractTask; + + + +public class HouseholdChoiceModelsTaskJppf extends AbstractTask { + + private transient HashMap propertyMap; + private transient MatrixDataServerIf ms; + private transient HouseholdDataManagerIf hhDataManager; + private transient ModelStructure modelStructure; + private transient TazDataIf tazDataManager; + private transient CtrampDmuFactoryIf dmuFactory; + private transient String restartModelString; + + private int startIndex; + private int endIndex; + private int taskIndex; + + private boolean runWithTiming; + + + + public HouseholdChoiceModelsTaskJppf( int taskIndex, int startIndex, int endIndex ) { + + this.startIndex = startIndex; + this.endIndex = endIndex; + this.taskIndex = taskIndex; + + runWithTiming = true; + } + + + public void run() { + + long startTime = System.nanoTime(); + + Logger logger = Logger.getLogger( "HouseholdChoiceModelsTaskJppf" ); + + String threadName = null; + try { + threadName = "[" + java.net.InetAddress.getLocalHost().getHostName() + "] " + Thread.currentThread().getName(); + } catch (UnknownHostException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + + + try { + DataProvider dataProvider = getDataProvider(); + + this.propertyMap = (HashMap) dataProvider.getParameter("propertyMap"); + this.ms = (MatrixDataServerIf) dataProvider.getParameter("ms"); + this.modelStructure = (ModelStructure) dataProvider.getParameter("modelStructure"); + this.tazDataManager = (TazDataIf) dataProvider.getParameter("tazDataManager"); + this.hhDataManager = (HouseholdDataManagerIf) dataProvider.getParameter("householdDataManager"); + this.dmuFactory = (CtrampDmuFactoryIf) dataProvider.getParameter("dmuFactory"); + this.restartModelString = (String) dataProvider.getParameter("restartModelString"); + + } catch (Exception e) { + e.printStackTrace(); + } + + // get the factory object used to create and recycle HouseholdChoiceModels objects. + HouseholdChoiceModelsManager modelManager = HouseholdChoiceModelsManager.getInstance( propertyMap, restartModelString, modelStructure, tazDataManager, dmuFactory ); + modelManager.managerSetup( ms ); + + + + HouseholdChoiceModels hhModel = modelManager.getHouseholdChoiceModelsObject( taskIndex); + + long setup1 = 0; + long setup2 = 0; + long setup3 = 0; + long setup4 = 0; + long setup5 = 0; + + setup1 = (System.nanoTime() - startTime)/1000000; + + HouseholdIf[] householdArray = hhDataManager.getHhArray( startIndex, endIndex ); + + setup2 = (System.nanoTime() - startTime)/1000000; + + hhModel.zeroTimes(); + for ( int i=0; i < householdArray.length; i++ ) { + + try { + if ( runWithTiming ) + hhModel.runModelsWithTiming ( householdArray[i] ); + else + hhModel.runModels ( householdArray[i] ); + } + catch (RuntimeException e) { + logger.fatal ( String.format("exception caught in taskIndex=%d hhModel index=%d applying hh model for i=%d, hhId=%d.", taskIndex, hhModel.getModelIndex(), i, householdArray[i].getHhId()) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + } + long[] componentTimes = hhModel.getTimes(); + long[] partialStopTimes = hhModel.getPartialStopTimes(); + + setup3 = (System.nanoTime() - startTime)/1000000; + + hhDataManager.setHhArray( householdArray, startIndex ); + + setup4 = (System.nanoTime() - startTime)/1000000; + + logger.info( String.format("end of household choice model thread=%s, task[%d], hhModel[%d], startIndex=%d, endIndex=%d", threadName, taskIndex, hhModel.getModelIndex(), startIndex, endIndex) ); + + setResult( (T)String.format("taskIndex=%d, hhModelInstance=%d, startIndex=%d, endIndex=%d, thread=%s", taskIndex, hhModel.getModelIndex(), startIndex, endIndex, threadName) ); + + setup5 = (System.nanoTime() - startTime)/1000000; + + logger.info( "task=" + taskIndex + ", setup=" + setup1 + ", getHhs=" + (setup2 - setup1) + ", processHhs=" + (setup3 - setup2) + ", putHhs=" + (setup4 - setup3) + ", return model=" + (setup5 - setup4) + "." ); + + if ( runWithTiming ) + logModelComponentTimes( componentTimes, partialStopTimes, logger, hhModel.getModelIndex() ); + + // this has to be the last statement in this method. + // add this hhModel instance to the static queue shared by other tasks of this type + modelManager.returnHouseholdChoiceModelsObject( hhModel, startIndex, endIndex ); + + } + + public String getId() { + return Integer.toString(taskIndex); + } + + private void logModelComponentTimes( long[] componentTimes, long[] partialStopTimes, Logger logger, int modelIndex ) { + + String[] label1 = { "AO", "FP", "CDAP", "IMTF", "IMTOD", "IMMC", "JTF", "JTDC", "JTTOD", "JTMC", "INMTF", "INMTDC", "INMTTOD", "INMTMC", "AWTF", "AWTDC", "AWTTOD", "AWTMC", "STF", "STDTM" }; + + logger.info( "Household choice model component runtimes (in ms) for task: " + taskIndex + ", modelIndex: " + modelIndex + ", startIndex: " + startIndex + ", endIndex: " + endIndex ); + + float total = 0; + for ( int i=0; i < componentTimes.length; i++ ) { + float time = (componentTimes[i]/1000000); + logger.info( String.format("%-6d%24s:%15.1f", (i+1), label1[i], time ) ); + total += time; + } + logger.info( String.format("%-6s%24s:%10.1f", "Total", "Total all components", total ) ); + logger.info( "" ); + + String[] label2 = { "SLC SOA", "SLC LS", "SLC", "SLC TOT", "S TOD", "S MC", "S PLC", "TOTAL" }; + + logger.info( "" ); + logger.info( "Times for parts of intermediate stop models:" ); + for ( int i=0; i < partialStopTimes.length; i++ ) { + float time = (partialStopTimes[i]/1000000); + logger.info( String.format("%-6d%24s:%15.1f", (i+1), label2[i], time ) ); + } + + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdCoordinatedDailyActivityPatternModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdCoordinatedDailyActivityPatternModel.java new file mode 100644 index 0000000..809c5a6 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdCoordinatedDailyActivityPatternModel.java @@ -0,0 +1,1049 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Random; + +import com.pb.common.calculator.VariableTable; +import com.pb.common.model.Alternative; +import com.pb.common.model.ConcreteAlternative; +import com.pb.common.model.LogitModel; +import com.pb.common.model.ModelException; +import com.pb.models.ctrampIf.CoordinatedDailyActivityPatternDMU; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.Definitions; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.common.newmodel.UtilityExpressionCalculator; +import com.pb.common.newmodel.ChoiceModelApplication; + +import org.apache.log4j.Logger; + + +/** + * Implements a coordinated daily activity pattern model, which is a joint choice of activity + * types of each member of a household. The class builds and applies separate choice models for + * households of sizes 1, 2, 3, 4, and 5. For households larger than 5, the persons in the household + * are ordered such that the first 5 members include up to 2 workers and 3 children (youngest to + * oldest), the 5-person model is applied for these 5 household members, than a separate, simple + * cross-sectional distribution is looked up for the remaining household members. + * + * The utilities are computed using four separate UEC spreadsheets. The first computes the activity + * utility for each person individually; the second computes the activity utility for each + * person when paired with each other person; the third computes the activity utility for each + * person when paired with each group of two other people in the household; and the fourth computes + * the activity utility considering all the members of the household. These utilities are then + * aggregated to represent each possible activity pattern for the household, and the choice is made. + * For households larger than 5, a second model is applied after the first, which selects a pattern + * for the 5+ household members from a predefined distribution. + * + * @author D. Ory + * + */ +public class HouseholdCoordinatedDailyActivityPatternModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdCoordinatedDailyActivityPatternModel.class); + private transient Logger cdapLogger = Logger.getLogger("cdap"); + + + private static final String PROPERTIES_UEC_DAILY_ACTIVITY_PATTERN = "UecFile.CoordinatedDailyActivityPattern"; + + private static final int UEC_DATA_PAGE = 0; + private static final int UEC_ONE_PERSON = 1; + private static final int UEC_TWO_PERSON = 2; + private static final int UEC_THREE_PERSON = 3; + private static final int UEC_ALL_PERSON = 4; + private static final int MAX_MODEL_HH_SIZE = 5; + + private static final String MANDATORY_PATTERN = Definitions.MANDATORY_PATTERN; + private static final String NONMANDATORY_PATTERN = Definitions.NONMANDATORY_PATTERN; + private static final String HOME_PATTERN = Definitions.HOME_PATTERN; + private static final String[] activityNameArray = { MANDATORY_PATTERN, NONMANDATORY_PATTERN, HOME_PATTERN }; + + + private ModelStructure modelStructure; + private double[][] fixedCumulativeProportions; + + // collection of logit models - one for each household size + private ArrayList logitModelList; + + // DMU for the UEC + private CoordinatedDailyActivityPatternDMU cdapDmuObject; + + // re-ordered collection of households + private PersonIf[] cdapPersonArray; + + // Four separate UECs to compute segments of the utility + private UtilityExpressionCalculator onePersonUec, twoPeopleUec, threePeopleUec, allMemberInteractionUec; + + + public HouseholdCoordinatedDailyActivityPatternModel( HashMap propertyMap, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + + this.modelStructure = modelStructure; + + // setup the coordinated daily activity pattern choice model objects + createLogitModels(); + setupCoordinatedDailyActivityPatternModelApplication( propertyMap, dmuFactory ); + + } + + + private void setupCoordinatedDailyActivityPatternModelApplication( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( "setting up CDAP choice model." ); + + // locate the coordinated daily activity pattern choice model UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String cdapUecFile = propertyMap.get( PROPERTIES_UEC_DAILY_ACTIVITY_PATTERN); + cdapUecFile = projectDirectory + cdapUecFile; + + + // create the coordinated daily activity pattern choice model DMU object. + cdapDmuObject = dmuFactory.getCoordinatedDailyActivityPatternDMU(); + + // create the uecs + onePersonUec = new UtilityExpressionCalculator( new File(cdapUecFile), UEC_ONE_PERSON, UEC_DATA_PAGE, propertyMap, (VariableTable)cdapDmuObject ); + twoPeopleUec = new UtilityExpressionCalculator( new File(cdapUecFile), UEC_TWO_PERSON, UEC_DATA_PAGE, propertyMap, (VariableTable)cdapDmuObject ); + threePeopleUec = new UtilityExpressionCalculator( new File(cdapUecFile), UEC_THREE_PERSON, UEC_DATA_PAGE, propertyMap, (VariableTable)cdapDmuObject ); + allMemberInteractionUec = new UtilityExpressionCalculator( new File(cdapUecFile), UEC_ALL_PERSON, UEC_DATA_PAGE, propertyMap, (VariableTable)cdapDmuObject ); + + //get the proportions by person type + double[][] fixedRelativeProportions = modelStructure.getCdap6PlusProps(); + fixedCumulativeProportions = new double[fixedRelativeProportions.length][]; + + // i loops over personTypes, 0 not used. + for ( int i=1; i < fixedRelativeProportions.length; i++ ) { + fixedCumulativeProportions[i] = new double[fixedRelativeProportions[i].length]; + + // j loops over cdap patterns, can skip index 0. + fixedCumulativeProportions[i][0] = fixedRelativeProportions[i][0]; + for ( int j=1; j < fixedRelativeProportions[i].length; j++ ) + fixedCumulativeProportions[i][j] = fixedCumulativeProportions[i][j-1] + fixedRelativeProportions[i][j]; + + // calculate the difference between 1.0 and the cumulative proportion and add to the Mandatory category (j==0) + // to make sure the cumulative propbabilities sum to exactly 1.0. + double diff = 1.0 - fixedCumulativeProportions[i][fixedRelativeProportions[i].length - 1]; + fixedCumulativeProportions[i][0] += diff; + } + + + } + + + public void applyModel( HouseholdIf hhObject ){ + + if ( hhObject.getDebugChoiceModels() ) + hhObject.logHouseholdObject( "Pre CDAP Household " + hhObject.getHhId() + " Object", cdapLogger ); + + + // get the activity pattern choice + String pattern = getCoordinatedDailyActivityPatternChoice( hhObject ); + + // set the pattern for the household + hhObject.setCoordinatedDailyActivityPatternResult( pattern ); + + + // set the pattern for each person and count by person type + PersonIf[] personArray = hhObject.getPersons(); + for(int j=1;j(MAX_MODEL_HH_SIZE); + + // build a model for each HH size + for(int i=0;i alternativeList = workingLogitModel.getAlternatives(); + for(int i=0;ij because if we have 1,2 for person 1, we don't also want 2,1; that's the + // same combination of two people + if(i>j) continue; + + // set the two person level dmu variables + cdapDmuObject.setPersonB(personB); + + // compute the two people utilities + double[] twoPersonUtilities = twoPeopleUec.solve(cdapDmuObject.getIndexValues(),cdapDmuObject,availability); + + // log these utilities for trace households + if(householdObject.getDebugChoiceModels()){ + + String stringToLog = String.format("%-30s%9d%9d%9s", "TwoPeople",(i+1),(j+1),"--"); + + for(int k=0;kk because if we have 1,2,3 for person 1, we don't also want 1,3,2; that's the + // same combination of three people + if(j>k) continue; + + PersonIf personC = getCdapPerson(k+1); + + // set the three level dmu variables + cdapDmuObject.setPersonC(personC); + + // compute the three person utilities + double[] threePersonUtilities = threePeopleUec.solve(cdapDmuObject.getIndexValues(),cdapDmuObject,availability); + + // log these utilities for trace households + if(householdObject.getDebugChoiceModels()){ + + String stringToLog = String.format("%-30s%9d%9d%9d", "ThreePeople",(i+1),(j+1),(k+1)); + + for(int l=0;lMAX_MODEL_HH_SIZE){ + + String allMembersChosenPattern = applyModelForExtraHhMembers(householdObject,firstFiveChosenName); + + // re-order the activities by the original order of persons + String finalHhPattern = ""; + String[] finalHhPatternActivities = new String[cdapPersonArray.length]; + for ( int i=1; i < cdapPersonArray.length; i++ ) { + int k = cdapPersonArray[i].getPersonNum(); + finalHhPatternActivities[k] = allMembersChosenPattern.substring( i-1, i ); + } + + for ( int i=1; i < cdapPersonArray.length; i++ ) + finalHhPattern += finalHhPatternActivities[i]; + + return finalHhPattern; + + } + + if(householdObject.getDebugChoiceModels()){ + // reset the logger to what it was before we changed it + LogitModel.setLogger( Logger.getLogger(LogitModel.class) ); + } + + + // no need to re-order the activities - hhsize <= MAX_MODEL_HH_SIZE have original order of persons + return firstFiveChosenName; + + + } + /** + * Applies a simple choice from fixed proportions by person type for members of households with more than + * 5 people who are not included in the CDAP model. The choices of the additional household + * members are independent of each other. + * + * @param householdObject + * @param patternStringForOtherHhMembers + * @return the pattern for the entire household, including the 5-member pattern chosen by the + * logit model and the additional members chosen by the fixed-distribution model. + * + */ + private String applyModelForExtraHhMembers( HouseholdIf householdObject, String patternStringForOtherHhMembers ){ + + String allMembersPattern = patternStringForOtherHhMembers; + + // get the persons not yet modeled + PersonIf[] personArray = getPersonsNotModeledByCdap(MAX_MODEL_HH_SIZE); + + // person array is 1-based to be consistent with other person arrays + for( int i=1; i cdapPersonArray.length - 1 ) { + logger.fatal( String.format("persNum value = %d is out of range for hhSize = %d", persNum, cdapPersonArray.length - 1) ); + throw new RuntimeException(); + } + + return cdapPersonArray[persNum]; + } + + /** + * Method returns an array of persons not modeled by the CDAP model (i.e. persons 6 to X, when + * ordered by the reOrderPersonsForCdap method + * @param personsModeledByCdap + * @return + */ + public PersonIf[] getPersonsNotModeledByCdap(int personsModeledByCdap){ + + // create a 1-based person array to be consistent + PersonIf[] personArray = null; + if ( cdapPersonArray.length > personsModeledByCdap + 1 ) + personArray = new PersonIf[cdapPersonArray.length - personsModeledByCdap]; + else + personArray = new PersonIf[0]; + + + for(int i=1;i propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + setupFreeParkingChoiceModelApplication( propertyMap, tazDataManager, dmuFactory ); + } + + + private void setupFreeParkingChoiceModelApplication(HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory) { + logger.info( "setting up free parking choice model." ); + + // locate the auto ownership UEC + String projectDirectory = propertyMap.get(CtrampApplication.PROPERTIES_PROJECT_DIRECTORY); + String fpUecFile = projectDirectory + propertyMap.get(FP_CONTROL_FILE_TARGET); + + // create the auto ownership choice model DMU object. + fpDmuObject = dmuFactory.getFreeParkingChoiceDMU(); + + // create the auto ownership choice model object + fpModel = new ChoiceModelApplication(fpUecFile,FP_MODEL_SHEET,FP_DATA_SHEET,propertyMap, (VariableTable)fpDmuObject ); + + } + + + public void applyModel(HouseholdIf hhObject){ + + // apply model at a person level, but use the same random number + // for all persons so the result is consistent with the ARC legacy code + Random hhRandom = hhObject.getHhRandom(); + double randomNumber = hhRandom.nextDouble(); + + // person array is 1-based + PersonIf[] person = hhObject.getPersons(); + for (int i=1; i 0) { + chosenAlt = fpModel.getChoiceResult(randomNumber); + } + else { + String errorMessage = String.format("Exception caught for HHID=%d, PERSID=%d, no available free parking alternatives to choose from in choiceModelApplication.", hhObj.getHhId(), personObj.getPersonId()); + logger.error (errorMessage); + throw new RuntimeException(); + } + + // write choice model alternative info to log file + if ( hhObj.getDebugChoiceModels() ) { + fpModel.logAlternativesInfo("Free parking Choice", String.format("PERS_%d", personObj.getPersonId())); + fpModel.logSelectionInfo ( "Free parking Choice", String.format("PERS_%d", personObj.getPersonId()), randomNumber, chosenAlt); + } + + return chosenAlt; + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndNonManDestChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndNonManDestChoiceModel.java new file mode 100644 index 0000000..b5bee04 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndNonManDestChoiceModel.java @@ -0,0 +1,452 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Random; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.TreeSet; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.common.util.IndexSort; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.jppf.DestinationSampleOfAlternativesModel; +import com.pb.models.ctrampIf.jppf.ModeChoiceModel; +import com.pb.common.newmodel.ChoiceModelApplication; + +import org.apache.log4j.Logger; + +public class HouseholdIndNonManDestChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdIndNonManDestChoiceModel.class); + private transient Logger dcNonManLogger = Logger.getLogger("tourDcNonMan"); + + + // TODO eventually remove this target + private static final String PROPERTIES_UEC_DEST_CHOICE = "UecFile.DestinationChoice"; + private static final String PROPERTIES_UEC_DEST_CHOICE_SOA = "UecFile.SampleOfAlternativesChoice"; + + private static final String PROPERTIES_NON_MAN_SOA_SAMPLE_SIZE_KEY = "IndividualNonMandatoryTourLocationChoice.SampleOfAlternatives.SampleSize"; + + private static final int DC_DATA_SHEET = 0; + + + + private String tourCategory; + private ModelStructure modelStructure; + + private String[] tourPurposeList; + private HashMap purposeModelIndexMap; + + private TourModeChoiceDMU mcDmuObject; + private DestChoiceDMU dcDmuObject; + private DcSoaDMU dcSoaDmuObject; + + + private ModeChoiceModel mcModel; + private DestinationSampleOfAlternativesModel dcSoaModel; + private ChoiceModelApplication dcModel[]; + + private int numberOfSubzones; + + private int modelIndex; + + + //public HouseholdIndNonManDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel, double[][][] indivNonManProbabilitiesCache, double[][][] indivNonManCumProbabilitiesCache ){ + public HouseholdIndNonManDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + this.tourCategory = ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY; + + logger.info ( String.format( "creating %s tour dest choice model instance", tourCategory ) ); + + // set the model structure and the tour purpose list + this.modelStructure = modelStructure; + this.mcModel = mcModel; + + // create an array of ChoiceModelApplication objects for each choice purpose + //setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory, indivNonManProbabilitiesCache, indivNonManCumProbabilitiesCache ); + setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory ); + + } + + + + //private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, double[][][] indivNonManProbabilitiesCache, double[][][] indivNonManCumProbabilitiesCache ) { + private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String dcUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE ); + dcUecFileName = projectDirectory + dcUecFileName; + + String soaUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE_SOA ); + soaUecFileName = projectDirectory + soaUecFileName; + + int soaSampleSize = getSoaSampleSize( propertyMap ); + + + + tourPurposeList = modelStructure.getDcModelPurposeList( this.tourCategory ); + + + numberOfSubzones = tazDataManager.getNumberOfSubZones(); + + + + dcDmuObject = dmuFactory.getDestChoiceDMU(); + dcSoaDmuObject = dmuFactory.getDcSoaDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + + + // setup the object for calculating destination choice attraction size terms and managing shadow price calculations. + DestChoiceSize dcSizeObj = new DestChoiceSize( modelStructure, tazDataManager ); + dcSizeObj.setupDestChoiceSize( propertyMap, projectDirectory, tourCategory ); + dcSizeObj.calculateDcSize(); + + + + dcDmuObject.setDestChoiceSize(dcSizeObj); + dcSoaDmuObject.setDestChoiceSizeObject(dcSizeObj); + + + // create a sample of alternatives choice model object for use in selecting a sample + // of all possible destination choice alternatives. + dcSoaModel = new DestinationSampleOfAlternativesModel( soaUecFileName, soaSampleSize, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, dcSoaDmuObject ); + + + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + int maxUecIndex = 0; + for ( String purposeName : tourPurposeList ) { + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + purposeModelIndexMap.put( purposeName, uecIndex ); + modelIndexSet.add( uecIndex ); + if ( uecIndex > maxUecIndex ) + maxUecIndex = uecIndex; + } + + dcModel = new ChoiceModelApplication[maxUecIndex+1]; + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + Iterator it = modelIndexSet.iterator(); + while ( it.hasNext() ) { + int m = it.next(); + dcModel[m] = new ChoiceModelApplication ( dcUecFileName, m, DC_DATA_SHEET, propertyMap, (VariableTable)dcDmuObject ); + } + + + } + + + + public void applyModel( HouseholdIf hh ) { + + // declare these variables here so their values can be logged if a RuntimeException occurs. + int i = -1; + int purposeIndex = -1; + String purposeName = ""; + + + PersonIf[] persons = hh.getPersons(); + + for ( i=1; i < persons.length; i++ ) { + + PersonIf p = persons[i]; + + // get the individual non-mandatory tours for this person and choose a destination for each. + int choiceNum = 0; + ArrayList tourList = p.getListOfIndividualNonMandatoryTours(); + for ( TourIf tour : tourList ) { + + purposeName = tour.getTourPurpose(); + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + + + int chosen = -1; + try { + + int homeTaz = hh.getHhTaz(); + int origTaz = tour.getTourOrigTaz(); + + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hh ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( tour ); + mcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0, hh.getDebugChoiceModels() ); + + // at destination choice stage for home based individual non-mandatory tours, time of day has not been selected, + // so use default mid-day to compute ms logsum. + mcDmuObject.setTourDepartPeriod( modelStructure.getNonMandatoryLocationDefaultDepartPeriod() ); + mcDmuObject.setTourArrivePeriod( modelStructure.getNonMandatoryLocationDefaultArrivePeriod() ); + + + // update the DC dmuObject for this person + dcDmuObject.setHouseholdObject( hh ); + dcDmuObject.setPersonObject( p ); + dcDmuObject.setTourObject(tour); + dcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0 ); + + // get the tour location alternative chosen from the sample + chosen = selectLocationFromSampleOfAlternatives( dcDmuObject, dcSoaDmuObject, mcDmuObject, tour, p, purposeName, purposeIndex, ++choiceNum ); + + } + catch (RuntimeException e) { + logger.fatal( String.format("exception caught selecting %s tour destination choice for hh.hhid=%d, personNum=%d, tourId=%d, purposeIndex=%d, purposeName=%s", tourCategory, hh.getHhId(), p.getPersonNum(), tour.getTourId(), purposeIndex, purposeName ) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + + // get zone, subzone from DC alternative + int chosenDestAlt = (chosen-1)/numberOfSubzones + 1; + int chosenShrtWlk = chosen - (chosenDestAlt-1)*numberOfSubzones - 1; + + // set chosen values in tour object + tour.setTourDestTaz( chosenDestAlt ); + tour.setTourDestWalkSubzone( chosenShrtWlk ); + + tour.setTourDepartPeriod( 0 ); + tour.setTourArrivePeriod( 0 ); + + } + + } + + hh.setInmtlRandomCount( hh.getHhRandomCount() ); + + } + + + + + + private int selectLocationFromSampleOfAlternatives( DestChoiceDMU dcDmuObject, DcSoaDMU dcSoaDmuObject, TourModeChoiceDMU mcDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex, int choiceNum ) { + + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + + HouseholdIf household = dcDmuObject.getHouseholdObject(); + + + // compute the sample of alternatives set for the person + dcSoaModel.computeDestinationSampleOfAlternatives( dcSoaDmuObject, tour, person, purposeName, purposeIndex ); + + // get sample of locations and correction factors for sample + int numUniqueAltsInSample = dcSoaModel.getNumUniqueAlts(); + int[] finalSample = dcSoaModel.getSampleOfAlternatives(); + float[] sampleCorrectionFactors = dcSoaModel.getSampleOfAlternativesCorrections(); + + + + + int numAlts = dcModel[uecIndex].getNumberOfAlternatives(); + + boolean[] destAltsAvailable = new boolean[numAlts+1]; + int[] destAltsSample = new int[numAlts+1]; + + // set the destAltsAvailable array to true for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsAvailable[k] = false; + + // set the destAltsSample array to 1 for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsSample[k] = 0; + + + // tour start/end hours were set as default values for this tour type in method that called this method + int logsumIndex = modelStructure.getPeriodCombinationIndex( tour.getTourDepartPeriod(), tour.getTourArrivePeriod() ); + + Logger modelLogger = dcNonManLogger; + String choiceModelDescription = String.format ( "Individual Non-Mandatory Tour Mode Choice Logsum calculation for %s Location Choice", purposeName ); + String decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + String loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + + + int[] sampleValues = new int[numUniqueAltsInSample+1]; + + // for the destinations and sub-zones in the sample, compute mc logsums and save in DC dmuObject. + // also save correction factor and set availability and sample value for the sample alternative to true. 1, respectively. + for (int i=1; i <= numUniqueAltsInSample; i++) { + + sampleValues[i] = finalSample[i]; + + int d = (finalSample[i]-1)/numberOfSubzones + 1; + int w = finalSample[i] - (d-1)*numberOfSubzones - 1; + + // dmuIndex values have already been set, but we need to change the destination zone value, so first get the set values and chenge the one index. + IndexValues indexValues = mcDmuObject.getDmuIndexValues(); + int origTaz = indexValues.getOriginZone(); + + // set the zone, walk subzone, start and end time values for the mcDmuObject and calculate the logsum. + mcDmuObject.setTourDestTaz( d ); + mcDmuObject.setTourDestWalkSubzone( w ); + + mcDmuObject.setDmuIndexValues( household.getHhId(), d, origTaz, d, household.getDebugChoiceModels() ); + + //create TVPB for trip mode choice model + mcModel.setTVPBValues(mcDmuObject, tour.getTourPrimaryPurpose()); + + if ( household.getDebugChoiceModels() ) { + household.logTourObject( loggingHeader + ", sample " + i , modelLogger, person, mcDmuObject.getTourObject() ); + } + + // get the mode choice logsum for the destination choice sample alternative + double logsum = mcModel.getModeChoiceLogsum( mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel ); + + // set logsum value in DC dmuObject for the sampled zone and subzone - for this long term choice model, set the AmPm logsum value. + dcDmuObject.setMcLogsum ( logsumIndex, d, w, logsum ); + + // set sample of alternatives correction factor used in destination choice utility for the sampled alternative. + dcDmuObject.setDcSoaCorrections( d, w, sampleCorrectionFactors[i] ); + + // set availaibility and sample values for the purpose, dcAlt. + destAltsAvailable[finalSample[i]] = true; + destAltsSample[finalSample[i]] = 1; + + } + + + String loggerString = ""; + String separator = ""; + + // log headers to traceLogger if the person making the destination choice is from a household requesting trace information + if ( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Individual Non-Mandatory Tour Destination Choice Model, Purpose=%s", purposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + + modelLogger.info(" "); + loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + dcModel[uecIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + // compute destination choice proportions and choose alternative + dcModel[uecIndex].computeUtilities ( dcDmuObject, dcDmuObject.getDmuIndexValues(), destAltsAvailable, destAltsSample ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( dcModel[uecIndex].getAvailabilityCount() > 0 ) + chosen = dcModel[uecIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, PersonNum=%d, no available %s destination choice alternatives to choose from in choiceModelApplication.", dcDmuObject.getHouseholdObject().getHhId(), dcDmuObject.getPersonObject().getPersonNum(), purposeName ) ); + throw new RuntimeException(); + } + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() ) { + + double[] utilities = dcModel[uecIndex].getUtilities(); + double[] probabilities = dcModel[uecIndex].getProbabilities(); + boolean[] availabilities = dcModel[uecIndex].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("--------------------- -------------- -------------- -------------- --------------"); + + int[] sortedSampleValueIndices = IndexSort.indexSort( sampleValues ); + + double cumProb = 0.0; + int selectedIndex = -1; + for(int j=1; j <= numUniqueAltsInSample; j++){ + + int k = sortedSampleValueIndices[j]; + int alt = finalSample[k]; + + if ( finalSample[k] == chosen ) + selectedIndex = j; + + int d = ( finalSample[k]-1) / numberOfSubzones + 1; + int w = finalSample[k] - (d-1)*numberOfSubzones - 1; + cumProb += probabilities[alt-1]; + String altString = String.format( "%-3d %5d %5d %5d", j, alt, d, w ); + modelLogger.info(String.format("%-21s%15s%18.6e%18.6e%18.6e", altString, availabilities[alt], utilities[alt-1], probabilities[alt-1], cumProb)); + } + + modelLogger.info(" "); + int d = (chosen-1)/numberOfSubzones + 1; + int w = chosen - (d-1)*numberOfSubzones - 1; + String altString = String.format( "%-3d %5d %5d %5d", selectedIndex, chosen, d, w ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + dcModel[uecIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + dcModel[uecIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + dcModel[uecIndex].logUECResults( modelLogger, loggerString ); + + + } + + + + return chosen; + + } + + + + public void setModelIndex( int index ){ + modelIndex = index; + } + + public int getModelIndex(){ + return modelIndex; + } + + + + + private int getSoaSampleSize( HashMap propertyMap ) { + + String propertyValue = ""; + propertyValue = propertyMap.get( PROPERTIES_NON_MAN_SOA_SAMPLE_SIZE_KEY ); + + int sampleSize = Integer.parseInt( propertyValue ); + + return sampleSize; + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourDepartureAndDurationTime.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourDepartureAndDurationTime.java new file mode 100644 index 0000000..b81b38b --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourDepartureAndDurationTime.java @@ -0,0 +1,1373 @@ +package com.pb.models.ctrampIf.jppf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.*; + +import com.pb.common.calculator.VariableTable; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourDepartureTimeAndDurationDMU; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; + +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 11, 2008 + * Time: 9:25:30 AM + * To change this template use File | Settings | File Templates. + */ +public class HouseholdIndividualMandatoryTourDepartureAndDurationTime implements Serializable { + + + private transient Logger logger = Logger.getLogger( HouseholdIndividualMandatoryTourDepartureAndDurationTime.class ); + private transient Logger todLogger = Logger.getLogger( "todLogger" ); + private transient Logger tourMCManLogger = Logger.getLogger( "tourMcMan" ); + + private static final String PROPERTIES_UEC_MAND_TOUR_DEP_TIME_AND_DUR = "UecFile.TourDepartureTimeAndDuration"; + + + // all the other page numbers are passed in + private static final int UEC_DATA_PAGE = 0; + private static final int UEC_WORK_MODEL_PAGE = 1; + private static final int UEC_UNIV_MODEL_PAGE = 2; + private static final int UEC_SCHOOL_MODEL_PAGE = 3; + + //work tod alts to log for the UEC logging + private static final int workAltsToLog = 300; + + private int[] areaType; + private int[] zoneTableRow; + + private int[] workTourDepartureTimeChoiceSample; + private int[] schoolTourDepartureTimeChoiceSample; + + + // DMU for the UEC + private TourDepartureTimeAndDurationDMU imtodDmuObject; + private TourModeChoiceDMU mcDmuObject; + + // model structure to compare the .properties time of day with the UECs + private ModelStructure modelStructure; + private String tourCategory = ModelStructure.MANDATORY_CATEGORY; + + private ChoiceModelApplication workTourChoiceModel; + private ChoiceModelApplication schoolTourChoiceModel; + private ChoiceModelApplication univTourChoiceModel; + private ModeChoiceModel mcModel; + + + private boolean[] needToComputeLogsum; + private double[] modeChoiceLogsums; + + private int[] altStarts; + private int[] altEnds; + + private int noAvailableWorkWindowCount = 0; + private int noAvailableSchoolWindowCount = 0; + + private int noUsualWorkLocationForMandatoryActivity = 0; + private int noUsualSchoolLocationForMandatoryActivity = 0; + + + + + public HouseholdIndividualMandatoryTourDepartureAndDurationTime( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + setupHouseholdIndividualMandatoryTourDepartureAndDurationTime ( propertyMap, tazDataManager, modelStructure, dmuFactory, mcModel ); + + } + + + private void setupHouseholdIndividualMandatoryTourDepartureAndDurationTime( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + logger.info( String.format( "setting up %s time-of-day choice model.", tourCategory ) ); + + // set the model structure + this.modelStructure = modelStructure; + this.mcModel = mcModel; + + + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + + + // locate the individual mandatory tour frequency choice model UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String imtodUecFile = propertyMap.get( PROPERTIES_UEC_MAND_TOUR_DEP_TIME_AND_DUR ); + imtodUecFile = projectDirectory + imtodUecFile; + + // get the dmu objects from the factory + imtodDmuObject = dmuFactory.getTourDepartureTimeAndDurationDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + + // set up the models + workTourChoiceModel = new ChoiceModelApplication( imtodUecFile, UEC_WORK_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)imtodDmuObject ); + schoolTourChoiceModel = new ChoiceModelApplication( imtodUecFile, UEC_SCHOOL_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)imtodDmuObject ); + univTourChoiceModel = new ChoiceModelApplication(imtodUecFile, UEC_UNIV_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable) imtodDmuObject); + + // get the alternatives table from the work tod UEC. + TableDataSet altsTable = workTourChoiceModel.getUEC().getAlternativeData(); + altStarts = altsTable.getColumnAsInt( CtrampApplication.START_FIELD_NAME ); + altEnds = altsTable.getColumnAsInt( CtrampApplication.END_FIELD_NAME ); + altsTable = null; + + imtodDmuObject.setTodAlts(altStarts, altEnds); + + + int numWorkDepartureTimeChoiceAlternatives = workTourChoiceModel.getNumberOfAlternatives(); + workTourDepartureTimeChoiceSample = new int[numWorkDepartureTimeChoiceAlternatives+1]; + Arrays.fill(workTourDepartureTimeChoiceSample, 1); + + int numSchoolDepartureTimeChoiceAlternatives = schoolTourChoiceModel.getNumberOfAlternatives(); + schoolTourDepartureTimeChoiceSample = new int[numSchoolDepartureTimeChoiceAlternatives+1]; + Arrays.fill(schoolTourDepartureTimeChoiceSample, 1); + + + + int numLogsumIndices = modelStructure.getPeriodCombinationIndices().length; + needToComputeLogsum = new boolean[numLogsumIndices]; + + modeChoiceLogsums = new double[numLogsumIndices]; + + + String[] tourPurposeList = modelStructure.getDcModelPurposeList( tourCategory ); + int workPurposeIndex = -1; + int univPurposeIndex = -1; + int schlPurposeIndex = -1; + for ( int i=0; i < tourPurposeList.length; i++ ) { + if ( workPurposeIndex < 0 && modelStructure.getDcModelPurposeIsWorkPurpose( tourPurposeList[i] )) + workPurposeIndex = i; + else if ( univPurposeIndex < 0 && modelStructure.getDcModelPurposeIsUniversityPurpose( tourPurposeList[i] )) + univPurposeIndex = i; + else if ( schlPurposeIndex < 0 && modelStructure.getDcModelPurposeIsSchoolPurpose( tourPurposeList[i] )) + schlPurposeIndex = i; + } + + } + + + public void applyModel( HouseholdIf household, boolean runModeChoice ){ + + Logger modelLogger = todLogger; + if ( household.getDebugChoiceModels() ) { + household.logHouseholdObject( "Pre Individual Mandatory Departure Time Choice Model HHID=" + household.getHhId(), modelLogger ); + household.logHouseholdObject( "Pre Individual Mandatory Tour Mode Choice Model HHID=" + household.getHhId(), tourMCManLogger ); + } + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + imtodDmuObject.setHousehold(household); + + + + // get the array of persons for this household + PersonIf[] personArray = household.getPersons(); + + // loop through the persons (1-based array) + for(int j=1;j 0 ){ + if(person.getPersonIsUniversityStudent() == 1) { + applyDepartureTimeChoiceForUnivTours(person, runModeChoice); + } + else { + applyDepartureTimeChoiceForSchoolTours(person, runModeChoice); + } + } + } + else if ( person.getPersonIsStudent() == 1 || person.getPersonIsPreschoolChild() == 1 ) { + if(person.getPersonIsUniversityStudent() == 1) { + applyDepartureTimeChoiceForUnivTours(person, runModeChoice); + } + else { + applyDepartureTimeChoiceForSchoolTours(person, runModeChoice); + } + if (person.getListOfWorkTours().size() > 0) + applyDepartureTimeChoiceForWorkTours(person, runModeChoice); + } + else { + if ( person.getListOfWorkTours().size() > 0 || person.getListOfSchoolTours().size() > 0 ) { + logger.error( String.format( "error mandatory departure time choice model for j=%d, hhId=%d, persNum=%d, personType=%s.", j, person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType() )); + logger.error( String.format( "person with type other than worker or student has %d work tours and %d school tours.", person.getListOfWorkTours().size(), person.getListOfSchoolTours().size() ) ); + throw new RuntimeException(); + } + } + + } + catch ( Exception e ) { + logger.error( String.format( "error mandatory departure time choice model for j=%d, hhId=%d, persId=%d, persNum=%d, personType=%s.", j, person.getHouseholdObject().getHhId(), person.getPersonId(), person.getPersonNum(), person.getPersonType() )); + throw new RuntimeException(); + } + + } + + + household.setImtodRandomCount( household.getHhRandomCount() ); + + + } + + + /** + * + * @param person object for which time choice should be made + * @return the number of work tours this person had scheduled. + */ + private int applyDepartureTimeChoiceForWorkTours( PersonIf person, boolean runModeChoice ) { + + Logger modelLogger = todLogger; + + // set the dmu object + imtodDmuObject.setPerson(person); + + HouseholdIf household = person.getHouseholdObject(); + + ArrayList workTours = person.getListOfWorkTours(); + + for ( int i=0; i < workTours.size(); i++ ) { + + TourIf t = workTours.get(i); + + // dest taz was set from result of usual school location choice when tour object was created in mandatory tour frequency model. + //TODO: if the destinationTaz value is -1, then this mandatory tour was created for a non-student (retired probably) + //TODO: and we have to resolve this somehow - either genrate a work/school location for retired, or change activity type for person. + //TODO: for now, we'll just skip the tour, and keep count of them. + int destinationTaz = t.getTourDestTaz(); + if ( destinationTaz <= 0 ) { + noUsualWorkLocationForMandatoryActivity++; + continue; + } + + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Individual Mandatory Work Tour Departure Time Choice Model for: Purpose=%s", t.getTourPrimaryPurpose() ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), t.getTourId(), workTours.size() ); + + workTourChoiceModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + String loggerString = "Individual Mandatory Work Tour Departure Time Choice Model: Debug Statement for Household ID: " + household.getHhId() + ", Person Num: " + person.getPersonNum() + ", Person Type: " + person.getPersonType() + ", Work Tour Id: " + t.getTourId() + " of " + workTours.size() + " work tours."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + + } + + + + + imtodDmuObject.setDestinationZone( destinationTaz ); + + // set the dmu object + imtodDmuObject.setTour( t ); + + + int originTaz = t.getTourOrigTaz(); + imtodDmuObject.setOriginZone( originTaz ); + + + // get and set the area types for the tour origin and usual work location zones + int tableRow = zoneTableRow[originTaz]; + imtodDmuObject.setOriginAreaType( areaType[tableRow-1] ); + + tableRow = zoneTableRow[destinationTaz]; + imtodDmuObject.setDestinationAreaType( areaType[tableRow-1] ); + + + + + + + // set the choice availability and initialize sample array - + // choicemodelapplication will change sample[] according to availability[] + boolean[] departureTimeChoiceAvailability = person.getAvailableTimeWindows(altStarts, altEnds); + Arrays.fill(workTourDepartureTimeChoiceSample, 1); + + if (departureTimeChoiceAvailability.length != workTourDepartureTimeChoiceSample.length) + { + logger.error( String.format( + "error in work departure time choice model for hhId=%d, persId=%d, persNum=%d, work tour %d of %d.", + person.getHouseholdObject().getHhId(), person.getPersonId(), person.getPersonNum(), i, workTours.size()) ); + logger.error(String .format( + "length of the availability array determined by the number of alternatiuves set in the person scheduler=%d", departureTimeChoiceAvailability.length) ); + logger.error(String.format( + "does not equal the length of the sample array determined by the number of alternatives in the work tour UEC=%d.", workTourDepartureTimeChoiceSample.length) ); + throw new RuntimeException(); + } + + // if no time window is available for the tour, make the first and last alternatives available + // for that alternative, and keep track of the number of times this condition occurs. + boolean noAlternativeAvailable = true; + for (int a = 0; a < departureTimeChoiceAvailability.length; a++) + { + if (departureTimeChoiceAvailability[a]) + { + noAlternativeAvailable = false; + break; + } + } + + if (noAlternativeAvailable) + { + noAvailableWorkWindowCount++; + departureTimeChoiceAvailability[1] = true; + departureTimeChoiceAvailability[departureTimeChoiceAvailability.length - 1] = true; + } + + + // check for multiple tours for this person + // set the first or second switch if multiple tours for person + if ( workTours.size() == 1 && person.getListOfSchoolTours().size() == 0 ) { + // not a multiple tour pattern + imtodDmuObject.setFirstTour( 0 ); + imtodDmuObject.setSubsequentTour( 0 ); + imtodDmuObject.setTourNumber( 1 ); + imtodDmuObject.setEndOfPreviousScheduledTour( 0 ); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + } + else if ( workTours.size() > 1 && person.getListOfSchoolTours().size() == 0 ) { + // Two work tour multiple tour pattern + if ( i == 0 ) { + // first of 2 work tours + imtodDmuObject.setFirstTour( 1 ); + imtodDmuObject.setSubsequentTour( 0 ); + imtodDmuObject.setTourNumber( i + 1 ); + imtodDmuObject.setEndOfPreviousScheduledTour( 0 ); + imtodDmuObject.setSubsequentTourIsWork(1); + imtodDmuObject.setSubsequentTourIsSchool(0); + } + else { + // second of 2 work tours + imtodDmuObject.setFirstTour( 0 ); + imtodDmuObject.setSubsequentTour( 1 ); + imtodDmuObject.setTourNumber( i + 1 ); + int otherTourArrivePeriod = workTours.get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this second work tour with depart <= first work tour departure AND arrive >= first work tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= workTours.get(0).getTourDepartPeriod() && endPeriod >= workTours.get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } + else if ( workTours.size() == 1 && person.getListOfSchoolTours().size() == 1 ) { + // One work tour, one school tour multiple tour pattern + if ( person.getPersonIsWorker() == 1 ) { + // worker, so work tour is first scheduled, school tour comes later. + imtodDmuObject.setFirstTour( 1 ); + imtodDmuObject.setSubsequentTour( 0 ); + imtodDmuObject.setTourNumber( 1 ); + imtodDmuObject.setEndOfPreviousScheduledTour( 0 ); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(1); + } + else { + // student, so school tour was already scheduled, this work tour is the second. + imtodDmuObject.setFirstTour( 0 ); + imtodDmuObject.setSubsequentTour( 1 ); + imtodDmuObject.setTourNumber( i + 1 ); + int otherTourArrivePeriod = person.getListOfSchoolTours().get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this work tour with depart <= first school tour departure AND arrive >= first school tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= person.getListOfSchoolTours().get(0).getTourDepartPeriod() && endPeriod >= person.getListOfSchoolTours().get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } + + + // calculate and store the mode choice logsum for the usual work location + // for this worker at the various + // departure time and duration alternativees + setWorkTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives(person, t, departureTimeChoiceAvailability); + + + + if( household.getDebugChoiceModels() ){ + household.logTourObject( loggingHeader, modelLogger, person, t ); + } + + + workTourChoiceModel.computeUtilities ( imtodDmuObject, imtodDmuObject.getIndexValues(), departureTimeChoiceAvailability, workTourDepartureTimeChoiceSample ); + + + Random hhRandom = imtodDmuObject.getDmuHouseholdObject().getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + + // if the choice model has no available alternatives, choose between the first and last alternative. + int chosen; + if ( workTourChoiceModel.getAvailabilityCount() > 0 ) + chosen = workTourChoiceModel.getChoiceResult( rn ); + else + chosen = rn < 0.5 ? 1 : altStarts.length; + + + + // schedule the chosen alternative + int chosenStartPeriod = altStarts[chosen-1]; + int chosenEndPeriod = altEnds[chosen-1]; + person.scheduleWindow( chosenStartPeriod, chosenEndPeriod ); + + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = workTourChoiceModel.getUtilities(); + double[] probabilities = workTourChoiceModel.getProbabilities(); + boolean[] availabilities = workTourChoiceModel.getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + ", Tour Id: " + t.getTourId() ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < workTourChoiceModel.getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d out=%-3d, in=%-3d", k+1, altStarts[k], altEnds[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d out=%-3d, in=%-3d", chosen, altStarts[chosen-1], altEnds[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + workTourChoiceModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + workTourChoiceModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel ); + workTourChoiceModel.logUECResults( modelLogger, loggingHeader, workAltsToLog ); + + } + + + if (runModeChoice) + { + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + + if ( household.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "Final Work Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", household.getHhId(), person.getPersonNum(), person.getPersonType() ); + household.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + return workTours.size(); + + } + + + private void setWorkTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives(PersonIf person, TourIf tour, boolean[] altAvailable) + { + + HouseholdIf household = person.getHouseholdObject(); + + Arrays.fill(needToComputeLogsum, true); + Arrays.fill(modeChoiceLogsums, -999); + + Logger modelLogger = todLogger; + String choiceModelDescription = String.format( "Work Tour Mode Choice Logsum calculation for %s Departure Time Choice", tour.getTourPrimaryPurpose() ); + String decisionMakerLabel = String.format( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId(), person.getListOfWorkTours().size() ); + String loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + + for (int a = 1; a <= altStarts.length; a++) + { + + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! altAvailable[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + if (needToComputeLogsum[index]) + { + + String periodString = modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(startPeriod)) + " to " + modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(endPeriod)); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, tour, startPeriod, endPeriod); + + if (household.getDebugChoiceModels()) + household.logTourObject(loggingHeader + ", " + periodString, modelLogger, person, mcDmuObject.getTourObject()); + + try + { + modeChoiceLogsums[index] = mcModel.getModeChoiceLogsum(mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel + ", " + periodString); + } catch(Exception e) + { + logger.fatal( "exception caught applying mcModel.getModeChoiceLogsum() for " + periodString + " work tour." ); + logger.fatal( "choiceModelDescription = " + choiceModelDescription ); + logger.fatal( "decisionMakerLabel = " + decisionMakerLabel ); + throw new RuntimeException(e); + } + needToComputeLogsum[index] = false; + } + + } + + imtodDmuObject.setModeChoiceLogsums(modeChoiceLogsums); + + mcDmuObject.getTourObject().setTourDepartPeriod(0); + mcDmuObject.getTourObject().setTourArrivePeriod(0); + } + + + private void setSchoolTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives(PersonIf person, TourIf tour, boolean[] altAvailable) + { + + HouseholdIf household = person.getHouseholdObject(); + + Arrays.fill(needToComputeLogsum, true); + Arrays.fill(modeChoiceLogsums, -999); + + Logger modelLogger = todLogger; + String choiceModelDescription = String.format( "School Tour Mode Choice Logsum calculation for %s Departure Time Choice", tour.getTourPrimaryPurpose() ); + String decisionMakerLabel = String.format( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId(), person.getListOfSchoolTours().size() ); + String loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + + for (int a = 1; a <= altStarts.length; a++) + { + + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! altAvailable[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + if (needToComputeLogsum[index]) + { + + String periodString = modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(startPeriod)) + " to " + modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(endPeriod)); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, tour, startPeriod, endPeriod); + + if (household.getDebugChoiceModels()) + household.logTourObject(loggingHeader + ", " + periodString, modelLogger, + person, mcDmuObject.getTourObject()); + + try + { + modeChoiceLogsums[index] = mcModel.getModeChoiceLogsum(mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel + ", " + periodString); + } catch(Exception e) + { + logger.error(e); + logger.fatal( "exception caught applying mcModel.getModeChoiceLogsum() for " + periodString + " school tour." ); + logger.fatal( "choiceModelDescription = " + choiceModelDescription ); + logger.fatal( "decisionMakerLabel = " + decisionMakerLabel ); + throw new RuntimeException(); + } + needToComputeLogsum[index] = false; + } + + } + + imtodDmuObject.setModeChoiceLogsums(modeChoiceLogsums); + + } + + + + /** + * + * @param person object for which time choice should be made + * @return the number of school tours this person had scheduled. + */ + private int applyDepartureTimeChoiceForSchoolTours( PersonIf person, boolean runModeChoice ) { + + Logger modelLogger = todLogger; + + // set the dmu object + imtodDmuObject.setPerson(person); + + HouseholdIf household = person.getHouseholdObject(); + + ArrayList schoolTours = person.getListOfSchoolTours(); + + for ( int i=0; i < schoolTours.size(); i++ ) { + + TourIf t = schoolTours.get(i); + + // dest taz was set from result of usual school location choice when tour object was created in mandatory tour frequency model. + //TODO: if the destinationTaz value is -1, then this mandatory tour was created for a non-student (retired probably) + //TODO: and we have to resolve this somehow - either genrate a work/school location for retired, or change activity type for person. + //TODO: for now, we'll just skip the tour, and keep count of them. + int destinationTaz = t.getTourDestTaz(); + if ( destinationTaz <= 0 ) { + noUsualSchoolLocationForMandatoryActivity++; + continue; + } + + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Individual Mandatory School Tour Departure Time Choice Model for: Purpose=%s", t.getTourPrimaryPurpose() ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), t.getTourId(), schoolTours.size() ); + + schoolTourChoiceModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + String loggerString = "Individual Mandatory School Tour Departure Time Choice Model: Debug Statement for Household ID: " + household.getHhId() + ", Person Num: " + person.getPersonNum() + ", Person Type: " + person.getPersonType() + ", Tour Id: " + t.getTourId() + " of " + schoolTours.size() + " school tours."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + } + + + + imtodDmuObject.setDestinationZone( destinationTaz ); + + // set the dmu object + imtodDmuObject.setTour( t ); + + int originTaz = t.getTourOrigTaz(); + imtodDmuObject.setOriginZone( originTaz ); + + + // get and set the area types for the tour origin and usual school location zones + int tableRow = zoneTableRow[originTaz]; + imtodDmuObject.setOriginAreaType( areaType[tableRow-1] ); + + tableRow = zoneTableRow[destinationTaz]; + imtodDmuObject.setDestinationAreaType( areaType[tableRow-1] ); + + + // set the choice availability and sample + boolean[] departureTimeChoiceAvailability = person.getAvailableTimeWindows(altStarts, + altEnds); + Arrays.fill(schoolTourDepartureTimeChoiceSample, 1); + + if (departureTimeChoiceAvailability.length != schoolTourDepartureTimeChoiceSample.length) + { + logger.error(String.format( + "error in school departure time choice model for hhId=%d, persId=%d, persNum=%d, school tour %d of %d.", + person.getHouseholdObject().getHhId(), person.getPersonId(), person.getPersonNum(), i, schoolTours.size()) ); + logger.error(String.format( + "length of the availability array determined by the number of alternatiuves set in the person scheduler=%d", departureTimeChoiceAvailability.length) ); + logger.error(String.format( + "does not equal the length of the sample array determined by the number of alternatives in the school tour UEC=%d.", schoolTourDepartureTimeChoiceSample.length) ); + throw new RuntimeException(); + } + + // if no time window is available for the tour, make the first and last + // alternatives available + // for that alternative, and keep track of the number of times this + // condition occurs. + boolean noAlternativeAvailable = true; + for (int a = 0; a < departureTimeChoiceAvailability.length; a++) + { + if (departureTimeChoiceAvailability[a]) + { + noAlternativeAvailable = false; + break; + } + } + + if (noAlternativeAvailable) + { + noAvailableSchoolWindowCount++; + departureTimeChoiceAvailability[1] = true; + schoolTourDepartureTimeChoiceSample[1] = 1; + departureTimeChoiceAvailability[departureTimeChoiceAvailability.length - 1] = true; + schoolTourDepartureTimeChoiceSample[schoolTourDepartureTimeChoiceSample.length - 1] = 1; + } + + // check for multiple tours for this person + // set the first or second switch if multiple tours for person + if (schoolTours.size() == 1 && person.getListOfWorkTours().size() == 0) + { + // not a multiple tour pattern + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + } else if (schoolTours.size() > 1 && person.getListOfWorkTours().size() == 0) + { + // Two school tour multiple tour pattern + if (i == 0) + { + // first of 2 school tours + imtodDmuObject.setFirstTour(1); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(i + 1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(1); + } else + { + // second of 2 school tours + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(1); + imtodDmuObject.setTourNumber(i + 1); + int otherTourArrivePeriod = schoolTours.get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this 2nd school tour with depart <= first school tour departure AND arrive >= first school tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= schoolTours.get(0).getTourDepartPeriod() && endPeriod >= schoolTours.get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } else if (schoolTours.size() == 1 && person.getListOfWorkTours().size() == 1) + { + // One school tour, one work tour multiple tour pattern + if (person.getPersonIsStudent() == 1) + { + // student, so school tour is first scheduled, work comes later. + imtodDmuObject.setFirstTour(1); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(1); + imtodDmuObject.setSubsequentTourIsSchool(0); + } else + { + // worker, so work tour was already scheduled, this school tour is the second. + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(1); + imtodDmuObject.setTourNumber(i + 1); + int otherTourArrivePeriod = person.getListOfWorkTours().get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this 2nd school tour with depart <= first work tour departure AND arrive >= first work tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= person.getListOfWorkTours().get(0).getTourDepartPeriod() && endPeriod >= person.getListOfWorkTours().get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } + + // calculate and store the mode choice logsum for the usual school location for this student at the various + // departure time and duration alternativees + setSchoolTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( person, t, departureTimeChoiceAvailability ); + + + if( household.getDebugChoiceModels() ) { + household.logTourObject( loggingHeader, modelLogger, person, t ); + } + + + schoolTourChoiceModel.computeUtilities ( imtodDmuObject, imtodDmuObject.getIndexValues(), departureTimeChoiceAvailability, schoolTourDepartureTimeChoiceSample ); + + + Random hhRandom = imtodDmuObject.getDmuHouseholdObject().getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has no available alternatives, choose between the first and last alternative. + int chosen; + if ( schoolTourChoiceModel.getAvailabilityCount() > 0 ) + chosen = schoolTourChoiceModel.getChoiceResult( rn ); + else + chosen = rn < 0.5 ? 1 : altStarts.length; + + + + // schedule the chosen alternative + int chosenStartPeriod = altStarts[chosen - 1]; + int chosenEndPeriod = altEnds[chosen - 1]; + try { + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + } + catch( Exception e ){ + logger.error("exception caught updating school tour TOD choice time windows."); + throw new RuntimeException(); + } + + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = schoolTourChoiceModel.getUtilities(); + double[] probabilities = schoolTourChoiceModel.getProbabilities(); + boolean[] availabilities = schoolTourChoiceModel.getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + ", Tour Id: " + t.getTourId() ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < schoolTourChoiceModel.getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d out=%-3d, in=%-3d", k+1, altStarts[k], altEnds[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d out=%-3d, in=%-3d", chosen, altStarts[chosen-1], altEnds[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + schoolTourChoiceModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + schoolTourChoiceModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel ); + schoolTourChoiceModel.logUECResults( modelLogger, loggingHeader, 20 ); + + } + + + if (runModeChoice) + { + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + + } + + if ( household.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "Final School Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", household.getHhId(), person.getPersonNum(), person.getPersonType() ); + household.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + return schoolTours.size(); + + } + + private void setUnivTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives(PersonIf person, TourIf tour, boolean[] altAvailable) + { + + HouseholdIf household = person.getHouseholdObject(); + + Arrays.fill(needToComputeLogsum, true); + Arrays.fill(modeChoiceLogsums, -999); + + Logger modelLogger = todLogger; + String choiceModelDescription = String.format( "University Tour Mode Choice Logsum calculation for %s Departure Time Choice", tour.getTourPrimaryPurpose() ); + String decisionMakerLabel = String.format( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId(), person.getListOfSchoolTours().size() ); + String loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + + for (int a = 1; a <= altStarts.length; a++) + { + + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! altAvailable[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + if (needToComputeLogsum[index]) + { + + String periodString = modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(startPeriod)) + " to " + modelStructure.getPeriodLabel(modelStructure.getPeriodIndex(endPeriod)); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, tour, startPeriod, endPeriod); + + if (household.getDebugChoiceModels()) + household.logTourObject(loggingHeader + ", " + periodString, modelLogger, person, mcDmuObject.getTourObject()); + + try + { + modeChoiceLogsums[index] = mcModel.getModeChoiceLogsum(mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel + ", " + periodString); + } catch(Exception e) + { + logger.error(e); + logger.fatal( "exception caught applying mcModel.getModeChoiceLogsum() for " + periodString + " university tour." ); + logger.fatal( "choiceModelDescription = " + choiceModelDescription ); + logger.fatal( "decisionMakerLabel = " + decisionMakerLabel ); + throw new RuntimeException(); + } + needToComputeLogsum[index] = false; + } + + } + + imtodDmuObject.setModeChoiceLogsums(modeChoiceLogsums); + + } + + /** + * + * @param person object for which time choice should be made + * @return the number of school tours this person had scheduled. + */ + private int applyDepartureTimeChoiceForUnivTours(PersonIf person, boolean runModeChoice) + { + + Logger modelLogger = todLogger; + + // set the dmu object + imtodDmuObject.setPerson(person); + + HouseholdIf household = person.getHouseholdObject(); + + ArrayList workTours = person.getListOfWorkTours(); + ArrayList schoolTours = person.getListOfSchoolTours(); + + for (int i = 0; i < schoolTours.size(); i++) + { + + TourIf t = schoolTours.get(i); + t.setTourDepartPeriod(-1); + t.setTourArrivePeriod(-1); + + // dest taz was set from result of usual school location choice when tour + // object was created in mandatory tour frequency model. + // TODO: if the destMgra value is -1, then this mandatory tour was + // created for a non-student (retired probably) + // TODO: and we have to resolve this somehow - either genrate a + // work/school location for retired, or change activity type for person. + // TODO: for now, we'll just skip the tour, and keep count of them. + int destMgra = t.getTourDestTaz(); + if (destMgra <= 0) + { + noUsualSchoolLocationForMandatoryActivity++; + continue; + } + + // write debug header + String separator = ""; + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if (household.getDebugChoiceModels()) + { + + choiceModelDescription = String.format( + "Individual Mandatory University Tour Departure Time Choice Model for: Purpose=%s", t.getTourPrimaryPurpose()); + decisionMakerLabel = String.format( + "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), t.getTourId(), schoolTours.size() ); + univTourChoiceModel.choiceModelUtilityTraceLoggerHeading(choiceModelDescription, decisionMakerLabel); + + modelLogger.info(" "); + String loggerString = "Individual Mandatory University Tour Departure Time Choice Model: Debug Statement for Household ID: " + household.getHhId() + ", Person Num: " + person.getPersonNum() + ", Person Type: " + person.getPersonType() + t.getTourId() + " of " + schoolTours.size() + " school tours."; + for (int k = 0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info(loggerString); + modelLogger.info(separator); + modelLogger.info(""); + modelLogger.info(""); + + } + + // set the dmu object + imtodDmuObject.setTour(t); + imtodDmuObject.setDestinationZone(destMgra); + imtodDmuObject.setOriginZone(t.getTourOrigTaz()); + + // set the choice availability and sample + boolean[] departureTimeChoiceAvailability = person.getAvailableTimeWindows(altStarts, altEnds); + Arrays.fill(schoolTourDepartureTimeChoiceSample, 1); + + if (departureTimeChoiceAvailability.length != schoolTourDepartureTimeChoiceSample.length) + { + logger.error(String.format( + "error in university departure time choice model for hhId=%d, persId=%d, persNum=%d, school tour %d of %d.", + person.getHouseholdObject().getHhId(), person.getPersonId(), person.getPersonNum(), i, schoolTours.size()) ); + logger.error(String.format( + "length of the availability array determined by the number of alternatives set in the person scheduler=%d", departureTimeChoiceAvailability.length) ); + logger.error(String.format( + "does not equal the length of the sample array determined by the number of alternatives in the university tour UEC=%d.", schoolTourDepartureTimeChoiceSample.length)); + throw new RuntimeException(); + } + + // if no time window is available for the tour, make the first and last + // alternatives available + // for that alternative, and keep track of the number of times this + // condition occurs. + boolean noAlternativeAvailable = true; + for (int a = 0; a < departureTimeChoiceAvailability.length; a++) + { + if (departureTimeChoiceAvailability[a]) + { + noAlternativeAvailable = false; + break; + } + } + + if (noAlternativeAvailable) + { + noAvailableSchoolWindowCount++; + departureTimeChoiceAvailability[1] = true; + schoolTourDepartureTimeChoiceSample[1] = 1; + departureTimeChoiceAvailability[departureTimeChoiceAvailability.length - 1] = true; + schoolTourDepartureTimeChoiceSample[schoolTourDepartureTimeChoiceSample.length - 1] = 1; + } + + // check for multiple tours for this person + // set the first or second switch if multiple tours for person + if (schoolTours.size() == 1 && person.getListOfWorkTours().size() == 0) + { + // not a multiple tour pattern + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + } else if (schoolTours.size() > 1 && person.getListOfWorkTours().size() == 0) + { + // Two school tour multiple tour pattern + if (i == 0) + { + // first of 2 school tours + imtodDmuObject.setFirstTour(1); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(i + 1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(1); + } else + { + // second of 2 school tours + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(1); + imtodDmuObject.setTourNumber(i + 1); + int otherTourArrivePeriod = schoolTours.get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this 2nd school tour with depart <= first school tour departure AND arrive >= first school tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= schoolTours.get(0).getTourDepartPeriod() && endPeriod >= schoolTours.get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } else if (schoolTours.size() == 1 && workTours.size() == 1) + { + // One school tour, one work tour multiple tour pattern + if (person.getPersonIsStudent() == 1) + { + // student, so school tour is first scheduled, work comes later. + imtodDmuObject.setFirstTour(1); + imtodDmuObject.setSubsequentTour(0); + imtodDmuObject.setTourNumber(1); + imtodDmuObject.setEndOfPreviousScheduledTour(0); + imtodDmuObject.setSubsequentTourIsWork(1); + imtodDmuObject.setSubsequentTourIsSchool(0); + } else + { + // worker, so work tour was already scheduled, this school tour is the second. + imtodDmuObject.setFirstTour(0); + imtodDmuObject.setSubsequentTour(1); + imtodDmuObject.setTourNumber(i + 1); + int otherTourArrivePeriod = person.getListOfWorkTours().get(0).getTourArrivePeriod(); + imtodDmuObject.setEndOfPreviousScheduledTour(otherTourArrivePeriod); + imtodDmuObject.setSubsequentTourIsWork(0); + imtodDmuObject.setSubsequentTourIsSchool(0); + + // block alternatives for this 2nd school tour with depart <= first work tour departure AND arrive >= first work tour arrival. + for (int a = 1; a <= altStarts.length; a++) + { + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! departureTimeChoiceAvailability[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + if ( startPeriod <= workTours.get(0).getTourDepartPeriod() && endPeriod >= workTours.get(0).getTourArrivePeriod() ) + departureTimeChoiceAvailability[a] = false; + } + } + } + + // calculate and store the mode choice logsum for the usual school + // location for this student at the various + // departure time and duration alternativees + setUnivTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives(person, t, departureTimeChoiceAvailability); + + if (household.getDebugChoiceModels()) + { + household.logTourObject(loggingHeader, modelLogger, person, t); + } + + univTourChoiceModel.computeUtilities(imtodDmuObject, imtodDmuObject.getIndexValues(), + departureTimeChoiceAvailability, schoolTourDepartureTimeChoiceSample); + + Random hhRandom = imtodDmuObject.getDmuHouseholdObject().getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has no available alternatives, choose between the + // first and last alternative. + int chosen; + if (univTourChoiceModel.getAvailabilityCount() > 0) + chosen = univTourChoiceModel.getChoiceResult(rn); + else + chosen = rn < 0.5 ? 1 : altStarts.length; + + // schedule the chosen alternative + int chosenStartPeriod = altStarts[chosen - 1]; + int chosenEndPeriod = altEnds[chosen - 1]; + try { + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + } + catch( Exception e ){ + logger.error("exception caught updating university tour TOD choice time windows."); + throw new RuntimeException(); + } + + t.setTourDepartPeriod(chosenStartPeriod); + t.setTourArrivePeriod(chosenEndPeriod); + + // debug output + if (household.getDebugChoiceModels()) + { + + double[] utilities = univTourChoiceModel.getUtilities(); + double[] probabilities = univTourChoiceModel.getProbabilities(); + boolean[] availabilities = univTourChoiceModel.getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + + ", Tour Id: " + t.getTourId()); + modelLogger + .info("Alternative Availability Utility Probability CumProb"); + modelLogger + .info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for (int k = 0; k < schoolTourChoiceModel.getNumberOfAlternatives(); k++) + { + cumProb += probabilities[k]; + String altString = String.format("%-3d out=%-3d, in=%-3d", k + 1, altStarts[k], + altEnds[k]); + modelLogger.info(String.format("%-20s%15s%18.6e%18.6e%18.6e", altString, + availabilities[k + 1], utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format("%-3d out=%-3d, in=%-3d", chosen, + altStarts[chosen - 1], altEnds[chosen - 1]); + modelLogger.info(String.format("Choice: %s, with rn=%.8f, randomCount=%d", + altString, rn, randomCount)); + + modelLogger.info(separator); + modelLogger.info(""); + modelLogger.info(""); + + // write choice model alternative info to debug log file + univTourChoiceModel.logAlternativesInfo(choiceModelDescription, + decisionMakerLabel); + univTourChoiceModel.logSelectionInfo(choiceModelDescription, decisionMakerLabel, + rn, chosen); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + univTourChoiceModel.logUECResults(modelLogger, loggingHeader, 200); + + } + + if (runModeChoice) + { + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // school location and subzone and departure time and duration are + // set for this school tour. + int chosenMode = -1; + chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + + if (household.getDebugChoiceModels()) + { + String decisionMakerLabel = String + .format( + "Final University Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", + household.getHhId(), person.getPersonNum(), person.getPersonType()); + household.logPersonObject(decisionMakerLabel, modelLogger, person); + } + + return schoolTours.size(); + + } + + private void setModeChoiceDmuAttributes(HouseholdIf household, PersonIf person, TourIf t, int startPeriod, int endPeriod) + { + + t.setTourDepartPeriod(startPeriod); + t.setTourArrivePeriod(endPeriod); + + // update the MC dmuObjects for this person + mcDmuObject.setHouseholdObject(household); + mcDmuObject.setPersonObject(person); + mcDmuObject.setTourObject(t); + mcDmuObject.setDmuIndexValues(household.getHhId(), household.getHhTaz(), t.getTourOrigTaz(), t.getTourDestTaz(), household.getDebugChoiceModels()); + + //create TVPB for tour mode choice model + mcModel.setTVPBValues(mcDmuObject, t.getTourPrimaryPurpose()); + + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourFrequencyModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourFrequencyModel.java new file mode 100644 index 0000000..3a7ddc3 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdIndividualMandatoryTourFrequencyModel.java @@ -0,0 +1,428 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Random; + +import org.apache.log4j.Logger; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.Definitions; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.IndividualMandatoryTourFrequencyDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.common.newmodel.ChoiceModelApplication; + +/** + * Implements an invidual mandatory tour frequency model, which selects the number of work, school, + * or work and school tours for each person who selects a mandatory activity. There are essentially + * seven separate models, one for each person type (full-time worker, part-time worker, university student, + * non working adults, retired, driving students, and non-driving students), except pre-school students. + * The choices are one work tour, two work tours, one school tour, two school tours, and one + * work and school tour. Availability arrays are defined for each person type. + * + * The UEC for the model has two additional matrix calcuation tabs, which computes the one-way walk distance + * and the round-trip auto time to work and/or school for the model. This allows us to compute the work and/or + * school time, by setting the DMU destination index, just using the UEC. + * + * @author D. Ory + * + */ +public class HouseholdIndividualMandatoryTourFrequencyModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdIndividualMandatoryTourFrequencyModel.class); + private transient Logger tourFreq = Logger.getLogger("tourFreq"); + + private static final int UEC_DATA_PAGE = 0; + private static final int UEC_MODEL_PAGE = 1; + + private static final String PROPERTIES_UEC_INDIV_MANDATORY_TOUR_FREQ = "UecFile.IndividualMandatoryTourFrequency"; + + private static final String MANDATORY_ACTIVITY = Definitions.MANDATORY_PATTERN; + + + // model results + private static final int CHOICE_ONE_WORK = 1; + private static final int CHOICE_TWO_WORK = 2; + private static final int CHOICE_ONE_SCHOOL = 3; + private static final int CHOICE_TWO_SCHOOL = 4; + public static final int CHOICE_WORK_AND_SCHOOL = 5; + + private static final String[] choiceResults = {"1 Work", "2 Work", "1 School", "2 School", "Wrk & Schl"}; + + + + private int[] areaType; + private int[] zoneTableRow; + + //protected HashMap countByPersonType; + + private IndividualMandatoryTourFrequencyDMU imtfDmuObject; + private ChoiceModelApplication choiceModelApplication; + + private transient Logger choiceModelLogger = Logger.getLogger("cmLogger"); + private String personChoiceModelDescription; + private String personDecisionMakerDescription; + private String personChoiceModelLoggingHeader; + private String personChoiceModelSeparator; + + private ModelStructure modelStructure; + + + /** + * Constructor establishes the ChoiceModelApplication, which applies the logit model via the UEC + * spreadsheet, and it also establishes the UECs used to compute the one-way walk distance to work + * and/or school and the round-trip auto time to work and/or school. The model must be the first UEC + * tab, the one-way distance calculations must be the second UEC tab, round-trip time must be + * the third UEC tab. + * @param dmuObject is the UEC dmu object for this choice model + * @param uecFileName is the UEC control file name + * @param resourceBundle is the application ResourceBundle, from which a properties file HashMap will be created for the UEC + * @param tazDataManager is the object used to interact with the zonal data table + * @param modelStructure is the ModelStructure object that defines segmentation and other model structure relate atributes + */ + public HouseholdIndividualMandatoryTourFrequencyModel( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + + setupHouseholdIndividualMandatoryTourFrequencyModel ( propertyMap, tazDataManager, modelStructure, dmuFactory ); + + } + + + private void setupHouseholdIndividualMandatoryTourFrequencyModel ( HashMap propertyMap, TazDataIf tazDataManager, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( "setting up IMTF choice model." ); + + this.modelStructure = modelStructure; + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // locate the individual mandatory tour frequency choice model UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String imtfUecFile = propertyMap.get( PROPERTIES_UEC_INDIV_MANDATORY_TOUR_FREQ ); + imtfUecFile = projectDirectory + imtfUecFile; + + // get the dmu object from the factory + imtfDmuObject = dmuFactory.getIndividualMandatoryTourFrequencyDMU(); + + // set up the model + choiceModelApplication = new ChoiceModelApplication( imtfUecFile, UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)imtfDmuObject ); + + // prepare the results array + //countByPersonType = new HashMap(); + + } + + + /** + * Applies the model for the array of households that are stored in the HouseholdDataManager. + * The results are summarized by person type. + * + * @param householdDataManager is the object containg the Household objects for which this model is to be applied. + */ + public void applyModel( HouseholdIf household ){ + + Logger modelLogger = tourFreq; + if ( household.getDebugChoiceModels() ) + household.logHouseholdObject( "Pre Individual Mandatory Tour Frequency Choice HHID=" + household.getHhId() + " Object", modelLogger ); + + + int choice = -1; + + + // get this household's person array + PersonIf[] personArray = household.getPersons(); + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + imtfDmuObject.setHousehold(household); + + // set the area type for the home taz + int tableRow = zoneTableRow[household.getHhTaz()]; + imtfDmuObject.setHomeTazAreaType( areaType[tableRow-1] ); + + // loop through the person array (1-based) + for(int j=1;j 0 ) + choice = choiceModelApplication.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for j=%d, activity=%s, HHID=%d, no available alternatives to choose from in choiceModelApplication.", j, activity, household.getHhId() ) ); + //throw new RuntimeException(); + } + + + if ( household.getDebugChoiceModels() || choice < 0 ){ + logPersonChoiceCalculations( household, person, choice, rn ); + } + + + if ( choice < 0 ) { + logger.error ( String.format( "Exception caught for j=%d, activity=%s, HHID=%d, no available alternatives to choose from in choiceModelApplication.", j, activity, household.getHhId() ) ); + throw new RuntimeException(); + } + + person.setImtfChoice ( choice ); + + // set the person choices + if(choice==CHOICE_ONE_WORK){ + person.createWorkTours( 1, 0, workPurpose, modelStructure ); + } + else if(choice==CHOICE_TWO_WORK){ + person.createWorkTours( 2, 0, workPurpose, modelStructure ); + } + else if(choice==CHOICE_ONE_SCHOOL){ + person.createSchoolTours( 1, 0, schoolPurpose, modelStructure ); + } + else if(choice==CHOICE_TWO_SCHOOL){ + person.createSchoolTours( 2, 0, schoolPurpose, modelStructure ); + } + else if(choice==CHOICE_WORK_AND_SCHOOL){ + person.createWorkTours( 1, 0, workPurpose, modelStructure ); + person.createSchoolTours( 1, 0, schoolPurpose, modelStructure ); + } + + } // mandatory activity if + else if(activity.equalsIgnoreCase(MANDATORY_ACTIVITY) && person.getPersonIsPreschoolChild() == 1){ + // pre-school child with mandatory activity type is assigned choice = 3 (1 school tour). + choice = 3; + + person.setImtfChoice ( choice ); + + + // get the school purpose name for a non-driving age person to use for preschool tour purpose + String schoolPurpose = modelStructure.getSchoolPurpose( 10 ); + person.createSchoolTours( 1, 0, schoolPurpose, modelStructure ); + } + + + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught for j=%d, activity=%s, HHID=%d", j, activity, household.getHhId() ) ); + throw new RuntimeException(); + } + + + } // j (person loop) + + + household.setImtfRandomCount( household.getHhRandomCount() ); + + } + + + private void setupPersonChoiceCalculationLogging( Logger aLogger, String choiceModelDescription, String decisionMakerDescription, String loggingHeader, String aSeparator ){ + choiceModelLogger = aLogger; + personChoiceModelDescription = choiceModelDescription; + personDecisionMakerDescription = decisionMakerDescription; + personChoiceModelLoggingHeader = loggingHeader; + personChoiceModelSeparator = aSeparator; + } + + private void logPersonChoiceCalculations( HouseholdIf household, PersonIf person, int chosenAlternative, double rn ) { + + int randomCount = household.getHhRandomCount(); + + double[] utilities = choiceModelApplication.getUtilities(); + double[] probabilities = choiceModelApplication.getProbabilities(); + + int personNum = person.getPersonNum(); + String personTypeString = person.getPersonType(); + choiceModelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + choiceModelLogger.info("Alternative Utility Probability CumProb"); + choiceModelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0;k countByPersonType; + private HashMap purposeIndexToNameMap; + + private IndividualNonMandatoryTourFrequencyDMU dmuObject; + private ChoiceModelApplication[] choiceModelApplication; + private TableDataSet alternativesTable; + + + private Map tourFrequencyIncreaseProbabilityMap; + private int[] maxTourFrequencyChoiceList; + + /** + * Constructor establishes the ChoiceModelApplication, which applies the logit model via the UEC + * spreadsheet, and it also establishes the UECs used to compute the one-way walk distance to work + * and/or school and the round-trip auto time to work and/or school. The model must be the first UEC + * tab, the one-way distance calculations must be the second UEC tab, round-trip time must be + * the third UEC tab. + * @param dmuObject is the UEC dmu object for this choice model + * @param uecFileName is the UEC control file name + * @param resourceBundle is the application ResourceBundle, from which a properties file HashMap will be created for the UEC + * @param tazDataManager is the object used to interact with the zonal data table + * @param modelStructure is the ModelStructure object that defines segmentation and other model structure relate atributes + */ + + + public HouseholdIndividualNonMandatoryTourFrequencyModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ){ + + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + setUpModels( propertyMap, dmuFactory ); + + } + + + + public void setUpModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ){ + + logger.info( String.format( "setting up %s tour frequency choice model.", ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY ) ); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String uecFileName = propertyMap.get( PROPERTIES_UEC_INDIV_NON_MANDATORY_TOUR_FREQ ); + uecFileName = projectDirectory + uecFileName; + + + dmuObject = dmuFactory.getIndividualNonMandatoryTourFrequencyDMU(); + + // set up the model + choiceModelApplication = new ChoiceModelApplication[NUM_PERSON_TYPE_MODEL_PAGES+1]; // one choice model for each person type that has model specified; Ones indexing for personType. + choiceModelApplication[1] = new ChoiceModelApplication( uecFileName, FT_WORKER_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[2] = new ChoiceModelApplication( uecFileName, PT_WORKER_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[3] = new ChoiceModelApplication( uecFileName, UNIVERSITY_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[4] = new ChoiceModelApplication( uecFileName, NONWORKER_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[5] = new ChoiceModelApplication( uecFileName, RETIRED_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[6] = new ChoiceModelApplication( uecFileName, DRIVING_STUDENT_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[7] = new ChoiceModelApplication( uecFileName, NON_DRIVING_STUDENT_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + choiceModelApplication[8] = new ChoiceModelApplication( uecFileName, PRESCHOOL_UEC_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + + + + + // the alternatives are the same for each person type; use the first choiceModelApplication to get its uec and from it, get the TableDataSet of alternatives + // to use to determine which tour purposes should be generated for the chose alternative. + alternativesTable = choiceModelApplication[1].getUEC().getAlternativeData(); + + // check the field names in the alternatives table; make sure the their order is as expected. + String[] fieldNames = alternativesTable.getColumnLabels(); + + purposeIndexToNameMap = new HashMap(); + purposeIndexToNameMap.put( 1, modelStructure.ESCORT_PURPOSE_NAME ); + purposeIndexToNameMap.put( 2, modelStructure.SHOPPING_PURPOSE_NAME ); + purposeIndexToNameMap.put( 3, modelStructure.OTH_MAINT_PURPOSE_NAME ); + purposeIndexToNameMap.put( 4, modelStructure.OTH_DISCR_PURPOSE_NAME ); + purposeIndexToNameMap.put( 5, modelStructure.EAT_OUT_PURPOSE_NAME ); + purposeIndexToNameMap.put( 6, modelStructure.SOCIAL_PURPOSE_NAME ); + + if ( ! fieldNames[0].equalsIgnoreCase("a") && ! fieldNames[0].equalsIgnoreCase("alt") ) { + logger.error ( "error while checking order of fields in IndividualNonMandatoryTourFrequencyModel alternatives file."); + logger.error ( String.format( "first field expected to be 'a' or 'alt' (case insensitive), but %s was found instead.", fieldNames[0] ) ); + throw new RuntimeException(); + } + else { + + for ( int i : purposeIndexToNameMap.keySet() ) { + String name = purposeIndexToNameMap.get(i).trim(); + if ( ! fieldNames[i].equalsIgnoreCase( name ) ) { + logger.error ( "error while checking order of fields in IndividualNonMandatoryTourFrequencyModel alternatives file."); + logger.error ( String.format( "field %d expected to be '%s' (case insensitive), but %s was found instead.", i, name, fieldNames[i] ) ); + throw new RuntimeException(); + } + } + } + + //load data used for tour frequency extension model + loadIndividualNonMandatoryIncreaseModelData( projectDirectory + propertyMap.get(PROPERTIES_TOUR_FREQUENCY_EXTENSION_PROBABILITIES_FILE)); + + } + + + + /** + * Applies the model for the array of households that are stored in the HouseholdDataManager. + * The results are summarized by person type. + * + * @param householdDataManager is the object containg the Household objects for which this model is to be applied. + */ + public void applyModel( HouseholdIf household ){ + + int modelIndex = -1; + int choice = -1; + String personTypeString = "Missing"; + + Logger modelLogger = tourFreq; + if ( household.getDebugChoiceModels() ) + household.logHouseholdObject( "Pre Individual Non-Mandatory Tour Frequency Choice HHID=" + household.getHhId() + " Object", modelLogger ); + + + //this will be an array with values 1 -> tours.length being the number of non-mandatory tours in each category + // this keeps it consistent with the way the alternatives are held in the alternatives file/arrays + float[] tours = null; + + + // prepare the results array + //countByPersonType = new HashMap(); + //int numPurposes = alternativesTable.getColumnLabels().length; + + + + // get this household's person array + PersonIf[] personArray = household.getPersons(); + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + dmuObject.setHouseholdObject(household); + + // set homeTazIsUrban to 1 if area type for the home taz is urban + int urban = 0; + if ( tazDataManager.getZoneIsUrban( household.getHhTaz() ) == 1 ) + urban = 1; + dmuObject.setHomeTazIsUrban( urban ); + + + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + + + // loop through the person array (1-based) + for(int j=1;j 0 ) + choice = choiceModelApplication[modelIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for j=%d, activity=%s, HHID=%d, no Non-Mandatory Tour Frequency alternatives available to choose from in choiceModelApplication.", j, activity, person.getHouseholdObject().getHhId() ) ); + throw new RuntimeException(); + } + + + + // create the non-mandatory tour objects for the choice made. +// createIndividualNonMandatoryTours ( person, choice ); + tours = runIndividualNonMandatoryToursIncreaseModel(person,choice); + createIndividualNonMandatoryTours_new(person,tours); + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] alternativeNames = choiceModelApplication[modelIndex].getAlternativeNames(); + double[] utilities = choiceModelApplication[modelIndex].getUtilities(); + double[] probabilities = choiceModelApplication[modelIndex].getProbabilities(); + + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("--------------------------------------------- -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < alternativeNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %-66s", k+1, getAlternativeNameFromChoice(k+1) ); + modelLogger.info(String.format("%-72s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %s", choice, getAlternativeNameFromChoice( choice ) ); + modelLogger.info( String.format("Original Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + altString = String.format( "%-3d %s", choice, getAlternativeNameFromModifiedChoice( tours ) ); + modelLogger.info( String.format("Revised Choice After Increase: %s", altString ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + choiceModelApplication[modelIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + choiceModelApplication[modelIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, choice ); + + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel; + + // write UEC calculation results to separate model specific log file + choiceModelApplication[modelIndex].logUECResults( modelLogger, loggingHeader ); + + } + + person.setInmtfChoice ( choice ); + + + } + + + + /* count the results by person type + if ( ! personTypeString.equalsIgnoreCase("Missing") ) { + + //new way + // count the results + int[] counterArray = (countByPersonType.containsKey(personTypeString)) ? + countByPersonType.get(personTypeString) : new int[numPurposes]; + for (int p=1; p < numPurposes; p++) + counterArray[p-1] += (int) tours[p]; + countByPersonType.put(personTypeString, counterArray); + + } + */ + + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught for j=%d, activity=%s, HHID=%d", j, activity, household.getHhId() ) ); + throw new RuntimeException(e); + } + + } // j (person loop) + + household.setInmtfRandomCount( household.getHhRandomCount() ); + + } + + + + private String getAlternativeNameFromChoice ( int choice ) { + + // use the 1s based choice value as the table row number + float[] rowValues = alternativesTable.getRowValues( choice ); + + String altName = ""; + + // rowValues is a 0s based indexed array, but the first field is the alternative number, + // and subsequent fields indicate the number of tours to be generated for the purpose corresponding to the field. + for ( int i=1; i < rowValues.length; i++ ) { + + int numTours = (int)rowValues[i]; + if ( numTours == 0 ) + continue; + + String purposeName = purposeIndexToNameMap.get(i); + if ( altName.length() == 0 ) + altName = String.format(", %d %s", numTours, purposeName); + else + altName += String.format(", %d %s", numTours, purposeName); + } + + if ( altName.length() == 0 ) + altName = "no tours"; + + return altName; + } + + private String getAlternativeNameFromModifiedChoice ( float[] rowValues ) { + + String altName = ""; + + // rowValues is a 0s based indexed array, but the first field is the alternative number, + // and subsequent fields indicate the nuimber of tours to be generated for the purpose corresponding to the field. + for ( int i=1; i < rowValues.length; i++ ) { + + int numTours = (int)rowValues[i]; + if ( numTours == 0 ) + continue; + + String purposeName = purposeIndexToNameMap.get(i); + if ( altName.length() == 0 ) + altName = String.format(", %d %s", numTours, purposeName); + else + altName += String.format(", %d %s", numTours, purposeName); + } + + if ( altName.length() == 0 ) + altName = "no tours"; + + return altName; + } + + /** + * Logs the results of the model. + * + public void logResults(){ + + logger.info(" "); + logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + logger.info("Individual Non-Mandatory Tour Frequency Model Results"); + + // count of model results + logger.info(" "); + String firstHeader = "Person type "; + String secondHeader = "----------------------------- "; + + + + String[] purposeNames = alternativesTable.getColumnLabels(); + int[] columnTotals = new int[purposeNames.length-1]; + + for( int i=0; i < columnTotals.length; i++ ) { + firstHeader += String.format("%12s", purposeNames[i+1]); + secondHeader += "----------- "; + } + + firstHeader += String.format("%12s","Total"); + secondHeader += "-----------"; + + logger.info(firstHeader); + logger.info(secondHeader); + + + + int lineTotal = 0; + for(int i=0;i(); + TableDataSet probabilityTable; + try { + probabilityTable = (new CSVFileReader().readFile(new File(filePath))); + } catch (IOException e) { + logger.error("Exception caught reading Individual Non-Mandatory Tour Frequency extension probability table.",e); + throw new RuntimeException(e); + } + + String personTypeColumnName = "person_type"; + String mandatoryTourParticipationColumnName = "mandatory_tour"; + String jointTourParticipationColumnName = "joint_tour"; + String nonMandatoryTourTypeColumn = "nonmandatory_tour_type"; + String zeroAdditionalToursColumnName = "0_tours"; + String oneAdditionalToursColumnName = "1_tours"; + String twoAdditionalToursColumnName = "2_tours"; + + for (int i = 1; i <= probabilityTable.getRowCount(); i++) { + int key = getTourIncreaseTableKey((int) probabilityTable.getValueAt(i,nonMandatoryTourTypeColumn), + (int) probabilityTable.getValueAt(i,personTypeColumnName), + ((int) probabilityTable.getValueAt(i,mandatoryTourParticipationColumnName)) == 1, + ((int) probabilityTable.getValueAt(i,jointTourParticipationColumnName)) == 1); + tourFrequencyIncreaseProbabilityMap.put(key, + new float[] {probabilityTable.getValueAt(i,zeroAdditionalToursColumnName), + probabilityTable.getValueAt(i,oneAdditionalToursColumnName), + probabilityTable.getValueAt(i,twoAdditionalToursColumnName)}); + } + } + + private float[] runIndividualNonMandatoryToursIncreaseModel(PersonIf person, int choice) { + // use the 1s based choice value as the table row number + // rowValues is a 0s based indexed array, but the first field is the alternative number, + // and subsequent fields indicate the nuimber of tours to be generated for the purpose corresponding to the field. + + HouseholdIf household = person.getHouseholdObject(); + + + int personType = person.getPersonTypeNumber(); + boolean participatedInMandatoryTour = person.getListOfWorkTours().size() > 0 || person.getListOfSchoolTours().size() > 0; + + boolean participatedInJointTour = false; + TourIf[] jointTours = person.getHouseholdObject().getJointTourArray(); + if (jointTours != null) { + for (TourIf t : jointTours) { + if ( t.getPersonInJointTour(person)) { + participatedInJointTour = true; + break; + } + } + } + + + float[] rowValues = null; + + boolean notDone = true; + while (notDone) { + + rowValues = alternativesTable.getRowValues(choice); + + int firstCount = tourCountSum(rowValues); + if ( firstCount == 0 || firstCount >= 5 ) //if 0 or 5+ tours already, we are done + break; + + for (int i = 1; i < rowValues.length; i++) { + + if (rowValues[i] < maxTourFrequencyChoiceList[i]) + continue; + + int newChoice=-1; + int key = getTourIncreaseTableKey( i, personType, participatedInMandatoryTour, participatedInJointTour ); + float[] probabilities = tourFrequencyIncreaseProbabilityMap.get( key ); + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + for (int j = 0; j < probabilities.length; j++) { + if ( rn <= probabilities[j] ) { + rowValues[i] += j; + newChoice=j; + break; + } + } + + // debug output + if( household.getDebugChoiceModels() ){ + + Logger modelLogger = tourFreq; + String[] alternativeNames = { "no additional", "1 additional", "2 additional" }; + + modelLogger.info("Individual Non-Mandatory Tour Frequency Increase Choice for tour purposeName=" + purposeIndexToNameMap.get( i ) + ", purposeIndex=" + i ); + modelLogger.info("Alternative Probability CumProb"); + modelLogger.info("--------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < alternativeNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %-15s", k+1, alternativeNames[k] ); + modelLogger.info(String.format("%-20s%18.6e%18.6e", altString, probabilities[k], cumProb)); + } + + modelLogger.info( String.format("choice: %s, with rn=%.8f, randomCount=%d", newChoice, rn, randomCount ) ); + + modelLogger.info(""); + modelLogger.info(""); + + } + + } + notDone = tourCountSum(rowValues) > 5; + } + + return rowValues; + } + + private int tourCountSum(float[] tours) { + //tours are located in indices 1 -> tours.length + int sum = 0; + for (int i = 1; i < tours.length; i++) + sum += tours[i]; + return sum; + } + + private int getTourIncreaseTableKey(int nonMandatoryTourType, + int personType, + boolean participatedInMandatoryTour, + boolean participatedInJointTour) { + return nonMandatoryTourType + + 100*personType + + 10000*(participatedInMandatoryTour ? 1 : 0) + + 100000*(participatedInJointTour ? 1 : 0); + } + + private void createIndividualNonMandatoryTours_new(PersonIf person, float[] tours) { + person.clearIndividualNonMandatoryToursArray(); + + for(int i = 1; i < tours.length; i++) { + int numTours = (int) tours[i]; + if (numTours > 0) + person.createIndividualNonMandatoryTours( numTours, purposeIndexToNameMap.get(i), modelStructure ); + } + } + + +// private void createIndividualNonMandatoryTours ( Person person, int choice ) { +// +// // use the 1s based choice value as the table row number +// float[] rowValues = alternativesTable.getRowValues( choice ); +// +// // rowValues is a 0s based indexed array, but the first field is the alternative number, +// // and subsequent fields indicate the nuimber of tours to be generated for the purpose corresponding to the field. +// for ( int i=1; i < rowValues.length; i++ ) { +// +// int numTours = (int)rowValues[i]; +// if ( numTours == 0 ) +// continue; +// +// String purposeName = purposeIndexToNameMap.get(i); +// +// person.createIndividualNonMandatoryTours( numTours, i, purposeName ); +// } +// +// } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdJointDestChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdJointDestChoiceModel.java new file mode 100644 index 0000000..4bc4601 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdJointDestChoiceModel.java @@ -0,0 +1,456 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Random; +import java.util.HashMap; +import java.util.TreeSet; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.common.util.IndexSort; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.jppf.ModeChoiceModel; +import com.pb.common.newmodel.ChoiceModelApplication; +import org.apache.log4j.Logger; + + + +public class HouseholdJointDestChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdJointDestChoiceModel.class); + private transient Logger dcNonManLogger = Logger.getLogger("tourDcNonMan"); + + // TODO eventually remove this target + private static final String PROPERTIES_UEC_DEST_CHOICE = "UecFile.DestinationChoice"; + private static final String PROPERTIES_UEC_DEST_CHOICE_SOA = "UecFile.SampleOfAlternativesChoice"; + + private static final String PROPERTIES_JOINT_SOA_SAMPLE_SIZE_KEY = "JointTourLocationChoice.SampleOfAlternatives.SampleSize"; + + private static final int DC_DATA_SHEET = 0; + + + + private String tourCategory; + private ModelStructure modelStructure; + + private String[] tourPurposeList; + private HashMap purposeModelIndexMap; + + private TourModeChoiceDMU mcDmuObject; + private DestChoiceDMU dcDmuObject; + private DcSoaDMU dcSoaDmuObject; + + + private ModeChoiceModel mcModel; + private DestinationSampleOfAlternativesModel dcSoaModel; + private ChoiceModelApplication dcModel[]; + + + private int numberOfSubzones; + + private int modelIndex; + + + +// public HouseholdJointDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel, double[][][] jointProbabilitiesCache, double[][][] jointCumProbabilitiesCache ){ + public HouseholdJointDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + + this.tourCategory = ModelStructure.JOINT_NON_MANDATORY_CATEGORY; + + logger.info ( String.format( "creating %s tour dest choice model instance", tourCategory ) ); + + // set the model structure and the tour purpose list + this.modelStructure = modelStructure; + this.mcModel = mcModel; + + // create an array of ChoiceModelApplication objects for each choice purpose + //setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory, jointProbabilitiesCache, jointCumProbabilitiesCache ); + setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory ); + + } + + + + //private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, double[][][] jointProbabilitiesCache, double[][][] jointCumProbabilitiesCache ) { + private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String dcUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE ); + dcUecFileName = projectDirectory + dcUecFileName; + + String soaUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE_SOA ); + soaUecFileName = projectDirectory + soaUecFileName; + + int soaSampleSize = getSoaSampleSize( propertyMap ); + + + + tourPurposeList = modelStructure.getDcModelPurposeList( this.tourCategory ); + + numberOfSubzones = tazDataManager.getNumberOfSubZones(); + + + + dcDmuObject = dmuFactory.getDestChoiceDMU(); + dcSoaDmuObject = dmuFactory.getDcSoaDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + + // setup the object for calculating destination choice attraction size terms and managing shadow price calculations. + //long time2 = System.currentTimeMillis(); + //System.out.println( "before new DestChoiceSize() " + (time2 - time1) ); + DestChoiceSize dcSizeObj = new DestChoiceSize( modelStructure, tazDataManager ); + + //long time3 = System.currentTimeMillis(); + //System.out.println( "before setupDestChoiceSize() " + (time3 - time2) ); + dcSizeObj.setupDestChoiceSize( propertyMap, projectDirectory, tourCategory ); + + //long time4 = System.currentTimeMillis(); + //System.out.println( "before calculateDcSize() " + (time4 - time3) ); + dcSizeObj.calculateDcSize(); + + + dcDmuObject.setDestChoiceSize(dcSizeObj); + dcSoaDmuObject.setDestChoiceSizeObject(dcSizeObj); + + + // create a sample of alternatives choice model object for use in selecting a sample + // of all possible destination choice alternatives. + dcSoaModel = new DestinationSampleOfAlternativesModel( soaUecFileName, soaSampleSize, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, dcSoaDmuObject ); + + + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + int maxUecIndex = 0; + for ( String purposeName : tourPurposeList ) { + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + purposeModelIndexMap.put( purposeName, uecIndex ); + modelIndexSet.add( uecIndex ); + if ( uecIndex > maxUecIndex ) + maxUecIndex = uecIndex; + } + + dcModel = new ChoiceModelApplication[maxUecIndex+1]; + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + Iterator it = modelIndexSet.iterator(); + while ( it.hasNext() ) { + int m = it.next(); + dcModel[m] = new ChoiceModelApplication ( dcUecFileName, m, DC_DATA_SHEET, propertyMap, (VariableTable)dcDmuObject ); + } + + } + + + + public void applyModel( HouseholdIf hh ) { + + // declare these variables here so their values can be logged if a RuntimeException occurs. + int i = -1; + int purposeIndex = -1; + String purposeName = ""; + + Logger modelLogger = dcNonManLogger; + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre Joint Tour Location Choice HHID=" + hh.getHhId() + " Object", modelLogger ); + + + + TourIf[] jt = hh.getJointTourArray(); + if ( jt == null ) + return; + + int choiceNum = 0; + for ( i=0; i < jt.length; i++ ) { + + TourIf tour = jt[i]; + + purposeName = tour.getTourPurpose(); + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + + // get a person object to use for the choice model - use first person added to joint tour + byte[] personsInTour = tour.getPersonNumArray(); + int personNum = personsInTour[0]; + PersonIf p = hh.getPersons()[personNum]; + + + int chosen = -1; + try { + + int homeTaz = hh.getHhTaz(); + int origTaz = tour.getTourOrigTaz(); + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hh ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( tour ); + mcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0, hh.getDebugChoiceModels() ); + + // at destination choice stage for home based joint non-mandatory tours, time of day has not been selected, + // so use default mid-day to compute ms logsum. + mcDmuObject.setTourDepartPeriod( modelStructure.getNonMandatoryLocationDefaultDepartPeriod() ); + mcDmuObject.setTourArrivePeriod( modelStructure.getNonMandatoryLocationDefaultArrivePeriod() ); + + + // update the DC dmuObject for this person + dcDmuObject.setHouseholdObject( hh ); + dcDmuObject.setPersonObject( p ); + dcDmuObject.setTourObject(tour); + dcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0 ); + + // get the tour location alternative chosen from the sample + chosen = selectLocationFromSampleOfAlternatives( dcDmuObject, dcSoaDmuObject, mcDmuObject, tour, p, purposeName, purposeIndex, ++choiceNum ); + + } + catch (RuntimeException e) { + logger.fatal( String.format("exception caught selecting %s tour destination choice for hh.hhid=%d, personNum=%d, i=%d, purposeIndex=%d, purposeName=%s", tourCategory, hh.getHhId(), personNum, i, purposeIndex, purposeName ) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + + + // get zone, subzone from DC alternative + int chosenDestAlt = (chosen-1)/numberOfSubzones + 1; + int chosenShrtWlk = chosen - (chosenDestAlt-1)*numberOfSubzones - 1; + + + tour.setTourDestTaz( chosenDestAlt ); + tour.setTourDestWalkSubzone( chosenShrtWlk ); + + tour.setTourDepartPeriod( 0 ); + tour.setTourArrivePeriod( 0 ); + + } + + hh.setJtlRandomCount( hh.getHhRandomCount() ); + + } + + + + private int selectLocationFromSampleOfAlternatives( DestChoiceDMU dcDmuObject, DcSoaDMU dcSoaDmuObject, TourModeChoiceDMU mcDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex, int choiceNum ) { + + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + + HouseholdIf household = dcDmuObject.getHouseholdObject(); + + + // compute the sample of alternatives set for the person + dcSoaModel.computeDestinationSampleOfAlternatives( dcSoaDmuObject, tour, person, purposeName, purposeIndex ); + + // get sample of locations and correction factors for sample + int numUniqueAltsInSample = dcSoaModel.getNumUniqueAlts(); + int[] finalSample = dcSoaModel.getSampleOfAlternatives(); + float[] sampleCorrectionFactors = dcSoaModel.getSampleOfAlternativesCorrections(); + + + int numAlts = dcModel[uecIndex].getNumberOfAlternatives(); + + boolean[] destAltsAvailable = new boolean[numAlts+1]; + int[] destAltsSample = new int[numAlts+1]; + + // set the destAltsAvailable array to true for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsAvailable[k] = false; + + // set the destAltsSample array to 1 for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsSample[k] = 0; + + + // tour start/end hours were set as default values for this tour type in method that called this method + int logsumIndex = modelStructure.getPeriodCombinationIndex( tour.getTourDepartPeriod(), tour.getTourArrivePeriod() ); + + Logger modelLogger = dcNonManLogger; + String choiceModelDescription = String.format ( "Joint Tour Mode Choice Logsum calculation for %s Location Choice", purposeName ); + String decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + String loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + + int[] sampleValues = new int[numUniqueAltsInSample+1]; + + // for the destinations and sub-zones in the sample, compute mc logsums and save in DC dmuObject. + // also save correction factor and set availability and sample value for the sample alternative to true. 1, respectively. + for (int i=1; i <= numUniqueAltsInSample; i++) { + + sampleValues[i] = finalSample[i]; + + int d = (finalSample[i]-1)/numberOfSubzones + 1; + int w = finalSample[i] - (d-1)*numberOfSubzones - 1; + + // dmuIndex values have already been set, but we need to change the destination zone value, so first get the set values and chenge the one index. + IndexValues indexValues = mcDmuObject.getDmuIndexValues(); + int origTaz = indexValues.getOriginZone(); + + // set the zone, walk subzone, start and end time values for the mcDmuObject and calculate the logsum. + mcDmuObject.setTourDestTaz( d ); + mcDmuObject.setTourDestWalkSubzone( w ); + + mcDmuObject.setDmuIndexValues( household.getHhId(), d, origTaz, d, household.getDebugChoiceModels() ); + + //create TVPB for trip mode choice model + mcModel.setTVPBValues(mcDmuObject, tour.getTourPrimaryPurpose()); + + if ( household.getDebugChoiceModels() ) { + household.logTourObject( loggingHeader + ", sample " + i , modelLogger, person, mcDmuObject.getTourObject() ); + } + + // get the mode choice logsum for the destination choice sample alternative + double logsum = mcModel.getModeChoiceLogsum( mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel ); + + // set logsum value in DC dmuObject for the sampled zone and subzone - for this long term choice model, set the AmPm logsum value. + dcDmuObject.setMcLogsum ( logsumIndex, d, w, logsum ); + + // set sample of alternatives correction factor used in destination choice utility for the sampled alternative. + dcDmuObject.setDcSoaCorrections( d, w, sampleCorrectionFactors[i] ); + + // set availaibility and sample values for the purpose, dcAlt. + destAltsAvailable[finalSample[i]] = true; + destAltsSample[finalSample[i]] = 1; + + } + + + + String loggerString = ""; + String separator = ""; + + // log headers to traceLogger if the person making the destination choice is from a household requesting trace information + if ( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Joint Tour Destination Choice Model, Purpose=%s", purposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + + modelLogger.info(" "); + loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + dcModel[uecIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + // compute destination choice proportions and choose alternative + dcModel[uecIndex].computeUtilities ( dcDmuObject, dcDmuObject.getDmuIndexValues(), destAltsAvailable, destAltsSample ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( dcModel[uecIndex].getAvailabilityCount() > 0 ) + chosen = dcModel[uecIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, PersonNum=%d, no available %s destination choice alternatives to choose from in choiceModelApplication.", dcDmuObject.getHouseholdObject().getHhId(), dcDmuObject.getPersonObject().getPersonNum(), purposeName ) ); + throw new RuntimeException(); + } + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() ) { + + double[] utilities = dcModel[uecIndex].getUtilities(); + double[] probabilities = dcModel[uecIndex].getProbabilities(); + boolean[] availabilities = dcModel[uecIndex].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("--------------------- -------------- -------------- -------------- --------------"); + + int[] sortedSampleValueIndices = IndexSort.indexSort( sampleValues ); + + double cumProb = 0.0; + int selectedIndex = -1; + for(int j=1; j <= numUniqueAltsInSample; j++){ + + int k = sortedSampleValueIndices[j]; + int alt = finalSample[k]; + + if ( finalSample[k] == chosen ) + selectedIndex = j; + + int d = ( finalSample[k]-1) / numberOfSubzones + 1; + int w = finalSample[k] - (d-1)*numberOfSubzones - 1; + cumProb += probabilities[alt-1]; + String altString = String.format( "%-3d %5d %5d %5d", j, alt, d, w ); + modelLogger.info(String.format("%-21s%15s%18.6e%18.6e%18.6e", altString, availabilities[alt], utilities[alt-1], probabilities[alt-1], cumProb)); + } + + modelLogger.info(" "); + int d = (chosen-1)/numberOfSubzones + 1; + int w = chosen - (d-1)*numberOfSubzones - 1; + String altString = String.format( "%-3d %5d %5d %5d", selectedIndex, chosen, d, w ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + dcModel[uecIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + dcModel[uecIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + dcModel[uecIndex].logUECResults( modelLogger, loggerString ); + + + } + + + return chosen; + + } + + + public void setModelIndex( int index ){ + modelIndex = index; + } + + + public int getModelIndex(){ + return modelIndex; + } + + + private int getSoaSampleSize( HashMap propertyMap ) { + + String propertyValue = ""; + propertyValue = propertyMap.get( PROPERTIES_JOINT_SOA_SAMPLE_SIZE_KEY ); + + int sampleSize = Integer.parseInt( propertyValue ); + + return sampleSize; + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/HouseholdSubTourDestChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/HouseholdSubTourDestChoiceModel.java new file mode 100644 index 0000000..7e6c2a8 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/HouseholdSubTourDestChoiceModel.java @@ -0,0 +1,470 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Random; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.TreeSet; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.common.util.IndexSort; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.jppf.DestinationSampleOfAlternativesModel; +import com.pb.models.ctrampIf.jppf.ModeChoiceModel; +import com.pb.common.newmodel.ChoiceModelApplication; +import org.apache.log4j.Logger; + +public class HouseholdSubTourDestChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(HouseholdSubTourDestChoiceModel.class); + private transient Logger dcNonManLogger = Logger.getLogger("tourDcNonMan"); + + // TODO eventually remove this target + private static final String PROPERTIES_UEC_DEST_CHOICE = "UecFile.DestinationChoice"; + private static final String PROPERTIES_UEC_DEST_CHOICE_SOA = "UecFile.SampleOfAlternativesChoice"; + + private static final String PROPERTIES_ATWORK_SOA_SAMPLE_SIZE_KEY = "AtWorkSubtourLocationChoice.SampleOfAlternatives.SampleSize"; + + private static final int DC_DATA_SHEET = 0; + + + + private String tourCategory; + private ModelStructure modelStructure; + + private String[] tourPurposeList; + private HashMap purposeModelIndexMap; + + private TourModeChoiceDMU mcDmuObject; + private DestChoiceDMU dcDmuObject; + private DcSoaDMU dcSoaDmuObject; + + + private ModeChoiceModel mcModel; + private DestinationSampleOfAlternativesModel dcSoaModel; + private ChoiceModelApplication dcModel[]; + + private int numberOfSubzones; + + private int modelIndex; + + + //public HouseholdSubTourDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel, double[][][] atWorkProbabilitiesCache, double[][][] atWorkCumProbabilitiesCache ){ + public HouseholdSubTourDestChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, ModeChoiceModel mcModel ){ + + this.tourCategory = ModelStructure.AT_WORK_CATEGORY; + + logger.info ( String.format( "creating %s subtour dest choice model instance", tourCategory ) ); + + // set the model structure and the tour purpose list + this.modelStructure = modelStructure; + this.mcModel = mcModel; + + // create an array of ChoiceModelApplication objects for each choice purpose + //setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory, atWorkProbabilitiesCache, atWorkCumProbabilitiesCache ); + setupDestChoiceModelArrays( propertyMap, tazDataManager, dmuFactory ); + + } + + + + //private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory, double[][][] atWorkProbabilitiesCache, double[][][] atWorkCumProbabilitiesCache ) { + private void setupDestChoiceModelArrays( HashMap propertyMap, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String dcUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE ); + dcUecFileName = projectDirectory + dcUecFileName; + + String soaUecFileName = propertyMap.get( PROPERTIES_UEC_DEST_CHOICE_SOA ); + soaUecFileName = projectDirectory + soaUecFileName; + + int soaSampleSize = getSoaSampleSize( propertyMap ); + + + + tourPurposeList = modelStructure.getDcModelPurposeList( this.tourCategory ); + + + numberOfSubzones = tazDataManager.getNumberOfSubZones(); + + + + dcDmuObject = dmuFactory.getDestChoiceDMU(); + dcSoaDmuObject = dmuFactory.getDcSoaDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + + // setup the object for calculating destination choice attraction size terms and managing shadow price calculations. + DestChoiceSize dcSizeObj = new DestChoiceSize( modelStructure, tazDataManager ); + dcSizeObj.setupDestChoiceSize( propertyMap, projectDirectory, tourCategory ); + dcSizeObj.calculateDcSize(); + + + + dcDmuObject.setDestChoiceSize(dcSizeObj); + dcSoaDmuObject.setDestChoiceSizeObject(dcSizeObj); + + + // create a sample of alternatives choice model object for use in selecting a sample + // of all possible destination choice alternatives. + dcSoaModel = new DestinationSampleOfAlternativesModel( soaUecFileName, soaSampleSize, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, dcSoaDmuObject ); + + + + // get the number of purposes and declare the array dimension to be this size. + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + int maxUecIndex = 0; + for ( String purposeName : tourPurposeList ) { + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + purposeModelIndexMap.put( purposeName, uecIndex ); + modelIndexSet.add( uecIndex ); + if ( uecIndex > maxUecIndex ) + maxUecIndex = uecIndex; + } + + dcModel = new ChoiceModelApplication[maxUecIndex+1]; + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + Iterator it = modelIndexSet.iterator(); + while ( it.hasNext() ) { + int m = it.next(); + dcModel[m] = new ChoiceModelApplication ( dcUecFileName, m, DC_DATA_SHEET, propertyMap, (VariableTable)dcDmuObject ); + } + + } + + + + public void applyModel ( HouseholdIf hh ) { + + // declare these variables here so their values can be logged if a RuntimeException occurs. + int i = -1; + int purposeIndex = -1; + String purposeName = ""; + + Logger modelLogger = dcNonManLogger; + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre Subtour Location Choice Household " + hh.getHhId() + " Object", modelLogger ); + + + + PersonIf[] persons = hh.getPersons(); + + for ( i=1; i < persons.length; i++ ) { + + PersonIf p = persons[i]; + + // get the at-work subtours for this person and choose a destination for each. + int choiceNum = 0; + ArrayList tourList = p.getListOfAtWorkSubtours(); + for ( TourIf tour : tourList ) { + + TourIf workTour = null; + int workTourIndex = 0; + workTourIndex = tour.getWorkTourIndexFromSubtourId( tour.getTourId() ); + workTour = p.getListOfWorkTours().get( workTourIndex ); + + purposeName = tour.getTourPurpose(); + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + + int chosen = -1; + try { + + int homeTaz = hh.getHhTaz(); + int origTaz = tour.getTourOrigTaz(); + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hh ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( tour ); + mcDmuObject.setWorkTourObject( workTour ); + + // at destination choice stage for work-based tours, time of day has not been selected for subtour, + // so use default mid-day time period to compute ms logsum. + mcDmuObject.setTourDepartPeriod( modelStructure.getNonMandatoryLocationDefaultDepartPeriod() ); + mcDmuObject.setTourArrivePeriod( modelStructure.getNonMandatoryLocationDefaultArrivePeriod() ); + mcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, -1, hh.getDebugChoiceModels() ); + + // update the DC dmuObject for this person + dcDmuObject.setHouseholdObject( hh ); + dcDmuObject.setPersonObject( p ); + dcDmuObject.setTourObject(tour); + dcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0 ); + + + if ( hh.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", p.getHouseholdObject().getHhId(), p.getPersonNum(), p.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, p ); + } + + + + // get the tour location alternative chosen from the sample + chosen = selectLocationFromSampleOfAlternatives( dcDmuObject, dcSoaDmuObject, mcDmuObject, tour, p, purposeName, purposeIndex, ++choiceNum ); + + } + catch (RuntimeException e) { + logger.fatal( String.format("exception caught selecting %s tour destination choice for hh.hhid=%d, personNum=%d, tourId=%d, purposeIndex=%d, purposeName=%s", tourCategory, hh.getHhId(), p.getPersonNum(), tour.getTourId(), purposeIndex, purposeName ) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + // get zone, subzone from DC alternative + int chosenDestAlt = (chosen-1)/numberOfSubzones + 1; + int chosenShrtWlk = chosen - (chosenDestAlt-1)*numberOfSubzones - 1; + + // set chosen values in tour object + tour.setTourDestTaz( chosenDestAlt ); + tour.setTourDestWalkSubzone( chosenShrtWlk ); + + tour.setTourDepartPeriod( 0 ); + tour.setTourArrivePeriod( 0 ); + + } + + } + + hh.setAwlRandomCount( hh.getHhRandomCount() ); + + } + + + + + + + private int selectLocationFromSampleOfAlternatives( DestChoiceDMU dcDmuObject, DcSoaDMU dcSoaDmuObject, TourModeChoiceDMU mcDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex, int choiceNum ) { + + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + + HouseholdIf household = dcDmuObject.getHouseholdObject(); + + + // compute the sample of alternatives set for the person + dcSoaModel.computeDestinationSampleOfAlternatives( dcSoaDmuObject, tour, person, purposeName, purposeIndex ); + + // get sample of locations and correction factors for sample + int numUniqueAltsInSample = dcSoaModel.getNumUniqueAlts(); + int[] finalSample = dcSoaModel.getSampleOfAlternatives(); + float[] sampleCorrectionFactors = dcSoaModel.getSampleOfAlternativesCorrections(); + + + + + int numAlts = dcModel[uecIndex].getNumberOfAlternatives(); + + boolean[] destAltsAvailable = new boolean[numAlts+1]; + int[] destAltsSample = new int[numAlts+1]; + + // set the destAltsAvailable array to true for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsAvailable[k] = false; + + // set the destAltsSample array to 1 for all destination choice alternatives for each purpose + for (int k=1; k <= numAlts; k++) + destAltsSample[k] = 0; + + + + // tour start/end hours were set as default values for this tour type in method that called this method + int logsumIndex = modelStructure.getPeriodCombinationIndex( tour.getTourDepartPeriod(), tour.getTourArrivePeriod() ); + + + Logger modelLogger = dcNonManLogger; + String choiceModelDescription = String.format ( "AtWork Subtour Mode Choice Logsum calculation for %s Location Choice", purposeName ); + String decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", household.getHhId(), person.getPersonNum(), person.getPersonType() ); + String loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + + + int[] sampleValues = new int[numUniqueAltsInSample+1]; + + // for the destinations and sub-zones in the sample, compute mc logsums and save in DC dmuObject. + // also save correction factor and set availability and sample value for the sample alternative to true. 1, respectively. + for (int i=1; i <= numUniqueAltsInSample; i++) { + + sampleValues[i] = finalSample[i]; + + int d = (finalSample[i]-1)/numberOfSubzones + 1; + int w = finalSample[i] - (d-1)*numberOfSubzones - 1; + + // dmuIndex values have already been set, but we need to change the destination zone value, so first get the set values and chenge the one index. + IndexValues indexValues = mcDmuObject.getDmuIndexValues(); + int origTaz = indexValues.getOriginZone(); + + // set the zone, walk subzone, start and end time values for the mcDmuObject and calculate the logsum. + mcDmuObject.setTourDestTaz( d ); + mcDmuObject.setTourDestWalkSubzone( w ); + mcDmuObject.setDmuIndexValues( household.getHhId(), household.getHhTaz(), origTaz, d, household.getDebugChoiceModels() ); + + //create TVPB for trip mode choice model + mcModel.setTVPBValues(mcDmuObject, tour.getTourPrimaryPurpose()); + + if ( household.getDebugChoiceModels() ) { + household.logTourObject( loggingHeader + ", sample " + i , modelLogger, person, mcDmuObject.getTourObject() ); + } + + // get the mode choice logsum for the destination choice sample alternative + double logsum = mcModel.getModeChoiceLogsum( mcDmuObject, tour.getTourPrimaryPurpose(), modelLogger, choiceModelDescription, decisionMakerLabel ); + + + // set logsum value in DC dmuObject for the sampled zone and subzone - for this long term choice model, set the AmPm logsum value. + dcDmuObject.setMcLogsum ( logsumIndex, d, w, logsum ); + + // set sample of alternatives correction factor used in destination choice utility for the sampled alternative. + dcDmuObject.setDcSoaCorrections( d, w, sampleCorrectionFactors[i] ); + + // set availaibility and sample values for the purpose, dcAlt. + destAltsAvailable[finalSample[i]] = true; + destAltsSample[finalSample[i]] = 1; + + } + + + String loggerString = ""; + String separator = ""; + + // log headers to traceLogger if the person making the destination choice is from a household requesting trace information + if ( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "%s Tour Destination Choice Model, Purpose=%s", tourCategory, purposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + + modelLogger.info(" "); + loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + dcModel[uecIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + + + + // compute destination choice proportions and choose alternative + dcModel[uecIndex].computeUtilities ( dcDmuObject, dcDmuObject.getDmuIndexValues(), destAltsAvailable, destAltsSample ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( dcModel[uecIndex].getAvailabilityCount() > 0 ) + chosen = dcModel[uecIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, PersonNum=%d, no available %s destination choice alternatives to choose from in choiceModelApplication.", dcDmuObject.getHouseholdObject().getHhId(), dcDmuObject.getPersonObject().getPersonNum(), purposeName ) ); + throw new RuntimeException(); + } + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() ) { + + double[] utilities = dcModel[uecIndex].getUtilities(); + double[] probabilities = dcModel[uecIndex].getProbabilities(); + boolean[] availabilities = dcModel[uecIndex].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("--------------------- -------------- -------------- -------------- --------------"); + + int[] sortedSampleValueIndices = IndexSort.indexSort( sampleValues ); + + double cumProb = 0.0; + int selectedIndex = -1; + for(int j=1; j <= numUniqueAltsInSample; j++){ + + int k = sortedSampleValueIndices[j]; + int alt = finalSample[k]; + + if ( finalSample[k] == chosen ) + selectedIndex = j; + + int d = ( finalSample[k]-1) / numberOfSubzones + 1; + int w = finalSample[k] - (d-1)*numberOfSubzones - 1; + cumProb += probabilities[alt-1]; + String altString = String.format( "%-3d %5d %5d %5d", j, alt, d, w ); + modelLogger.info(String.format("%-21s%15s%18.6e%18.6e%18.6e", altString, availabilities[alt], utilities[alt-1], probabilities[alt-1], cumProb)); + } + + modelLogger.info(" "); + int d = (chosen-1)/numberOfSubzones + 1; + int w = chosen - (d-1)*numberOfSubzones - 1; + String altString = String.format( "%-3d %5d %5d %5d", selectedIndex, chosen, d, w ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + dcModel[uecIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + dcModel[uecIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + dcModel[uecIndex].logUECResults( modelLogger, loggerString ); + + + } + + + return chosen; + + } + + + + public void setModelIndex( int index ){ + modelIndex = index; + } + + public int getModelIndex(){ + return modelIndex; + } + + + + + private int getSoaSampleSize( HashMap propertyMap ) { + + String propertyValue = ""; + propertyValue = propertyMap.get( PROPERTIES_ATWORK_SOA_SAMPLE_SIZE_KEY ); + + int sampleSize = Integer.parseInt( propertyValue ); + + return sampleSize; + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/JointTourModels.java b/src/java/com/pb/models/ctrampIf/jppf/JointTourModels.java new file mode 100644 index 0000000..8797e48 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/JointTourModels.java @@ -0,0 +1,808 @@ +package com.pb.models.ctrampIf.jppf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.net.UnknownHostException; +import java.util.*; + +import com.pb.common.calculator.IndexValues; +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.JointTourFrequencyDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 11, 2008 + * Time: 9:25:30 AM + * To change this template use File | Settings | File Templates. + */ +public class JointTourModels implements Serializable { + + + private transient Logger logger = Logger.getLogger( JointTourModels.class ); + private transient Logger tourFreq = Logger.getLogger("tourFreq"); + + + private static final String PROPERTIES_UEC_JOINT_TOUR_FREQUENCY = "UecFile.JointTourFrequency"; + + + // all the other page numbers are passed in + private static final int UEC_DATA_PAGE = 0; + private static final int UEC_JOINT_TOUR_FREQ_MODEL_PAGE = 1; + private static final int UEC_JOINT_TOUR_COMPOSITION_MODEL_PAGE = 2; + private static final int UEC_JOINT_TOUR_PARTICIPATION_MODEL_PAGE = 3; + +// private static final int JOINT_TOUR_COMPOSITION_ADULTS = 1; +// private static final int JOINT_TOUR_COMPOSITION_CHILDREN = 2; +// private static final int JOINT_TOUR_COMPOSITION_MIXED = 3; + + public static final String[] JOINT_TOUR_COMPOSITION_NAMES = { "", "adult", "child", "mixed" }; + + + // DMU for the UEC + private JointTourFrequencyDMU dmuObject; + + // model structure to compare the .properties time of day with the UECs + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + + private ChoiceModelApplication jointTourFrequencyModel; + private ChoiceModelApplication jointTourComposition; + private ChoiceModelApplication jointTourParticipation; + + //protected int[][] jointTourChoiceFreq; + private int[] invalidCount = new int[5]; + + private String threadName = null; + + private String shoppingPurposeString; + private String eatOutPurposeString; + private String maintPurposeString; + private String discrPurposeString; + private String socialPurposeString; + + private int shoppingPurposeIndex; + private int eatOutPurposeIndex; + private int maintPurposeIndex; + private int discrPurposeIndex; + private int socialPurposeIndex; + + + public JointTourModels( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ){ + + // set the model structure + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + + try { + threadName = "[" + java.net.InetAddress.getLocalHost().getHostName() + ": " + Thread.currentThread().getName() + "]"; + } catch (UnknownHostException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + + setUpModels( propertyMap, dmuFactory ); + } + + + public void setUpModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ){ + + logger.info( String.format( "setting up %s tour frequency model on %s", ModelStructure.JOINT_NON_MANDATORY_CATEGORY, threadName ) ); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String uecFileName = propertyMap.get( PROPERTIES_UEC_JOINT_TOUR_FREQUENCY ); + uecFileName = projectDirectory + uecFileName; + + + dmuObject = dmuFactory.getJointTourFrequencyDMU(); + + shoppingPurposeString = modelStructure.getShoppingPurposeName(); + shoppingPurposeIndex = modelStructure.getDcModelPurposeIndex( shoppingPurposeString ); + eatOutPurposeString = modelStructure.getEatOutPurposeName(); + eatOutPurposeIndex = modelStructure.getDcModelPurposeIndex( eatOutPurposeString ); + maintPurposeString = modelStructure.getOthMaintPurposeName(); + maintPurposeIndex = modelStructure.getDcModelPurposeIndex( maintPurposeString ); + discrPurposeString = modelStructure.getOthDiscrPurposeName(); + discrPurposeIndex = modelStructure.getDcModelPurposeIndex( discrPurposeString ); + socialPurposeString = modelStructure.getSocialPurposeName(); + socialPurposeIndex = modelStructure.getDcModelPurposeIndex(socialPurposeString); + + + // set up the models + jointTourFrequencyModel = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_FREQ_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject); + jointTourComposition = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_COMPOSITION_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject); + jointTourParticipation = new ChoiceModelApplication(uecFileName, UEC_JOINT_TOUR_PARTICIPATION_MODEL_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject); + + } + + + public void applyModel( HouseholdIf household ) { + + try { + + household.calculateTimeWindowOverlaps(); + + // joint tour frequency choice is not applied to a household unless it has: + // 2 or more persons, each with at least one out-of home activity, and at least 1 of the persons not a pre-schooler. + + Logger modelLogger = tourFreq; + if ( household.getDebugChoiceModels() ) + household.logHouseholdObject( "Pre Joint Tour Frequency Choice HHID=" + household.getHhId() + " Object", modelLogger ); + + + // if it's not a valid household for joint tour frequency, keep track of count for logging later, and return. + int validIndex = household.getValidHouseholdForJointTourFrequencyModel(); + if ( validIndex != 1 ) { + invalidCount[validIndex]++; + switch ( validIndex ) { + case 2: household.setJointTourFreqResult( -2, "-2_1 person" ); break; + case 3: household.setJointTourFreqResult( -3, "-3_< 2 travel" ); break; + case 4: household.setJointTourFreqResult( -4, "-4_only preschool travel" ); break; + } + return; + } + + + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + dmuObject.setHouseholdObject(household); + + // get and set the area type indicaters for the hh taz + int hhTaz = household.getHhTaz(); + + int urban = tazDataManager.getZoneIsUrban( hhTaz ); + dmuObject.setHomeTazIsUrban( urban ); + + int suburban = tazDataManager.getZoneIsSuburban( hhTaz ); + dmuObject.setHomeTazIsSuburban( suburban ); + dmuObject.setWalkRetailAccessibility(tazDataManager.getNonMotorizedRetailAccessibity()[hhTaz]); + + IndexValues index = dmuObject.getDmuIndexValues(); + //if ( household.getHhId() == 306640 ) + // index.setDebug( true ); + + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Joint Non-Mandatory Tour Frequency Choice Model:" ); + decisionMakerLabel = String.format ( "HH=%d, hhSize=%d.", household.getHhId(), household.getHhSize() ); + + jointTourFrequencyModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + jointTourFrequencyModel.computeUtilities ( dmuObject, index ); + + // get the random number from the household + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int chosenFreqAlt = -1; + if ( jointTourFrequencyModel.getAvailabilityCount() > 0 ) { + chosenFreqAlt = jointTourFrequencyModel.getChoiceResult( rn ); + household.setJointTourFreqResult( chosenFreqAlt, jointTourFrequencyModel.getAlternativeNames()[chosenFreqAlt-1] ); + } + else { + logger.error ( String.format( "Exception caught for HHID=%d, no available joint tour frequency alternatives to choose from in choiceModelApplication.", household.getHhId() ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] altNames = jointTourFrequencyModel.getAlternativeNames(); + + double[] utilities = jointTourFrequencyModel.getUtilities(); + double[] probabilities = jointTourFrequencyModel.getProbabilities(); + + modelLogger.info("HHID: " + household.getHhId() + ", HHSize: " + household.getHhSize() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < altNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %10s", k+1, altNames[k] ); + modelLogger.info(String.format("%-15s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %10s", chosenFreqAlt, altNames[chosenFreqAlt-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + jointTourFrequencyModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + jointTourFrequencyModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosenFreqAlt ); + + // write UEC calculation results to separate model specific log file + jointTourFrequencyModel.logUECResults( modelLogger, loggingHeader ); + + } + + + createJointTours ( household, chosenFreqAlt ); + + + + // can skip composition choice if chosen alt is 1 -- no joint tours; just count the number of times alt 1 is chosen + // in tour frequency. + if ( chosenFreqAlt > 1 ) { + + TourIf[] jointTours = household.getJointTourArray(); + for ( int i=0; i < jointTours.length; i++ ) { + + dmuObject.setTourObject( jointTours[i] ); + + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Joint Tour Composition Choice Model:" ); + decisionMakerLabel = String.format ( "HH=%d, hhSize=%d, tourId=%d.", household.getHhId(), household.getHhSize(), jointTours[i].getTourId() ); + + jointTourComposition.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + + jointTourComposition.computeUtilities ( dmuObject, index ); + + + // get the random number from the household + random = household.getHhRandom(); + randomCount = household.getHhRandomCount(); + rn = random.nextDouble(); + + + + // if the choice model has at least one available alternative, make choice. + int chosenComposition = -1; + if ( jointTourComposition.getAvailabilityCount() > 0 ) + chosenComposition = jointTourComposition.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, joint tour i=%d, no available joint tour composition alternatives to choose from in choiceModelApplication.", household.getHhId(), i ) ); + throw new RuntimeException(); + } + + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] altNames = jointTourComposition.getAlternativeNames(); + + double[] utilities = jointTourComposition.getUtilities(); + double[] probabilities = jointTourComposition.getProbabilities(); + + modelLogger.info("HHID: " + household.getHhId() + ", HHSize: " + household.getHhSize() + ", tourId: " + jointTours[i].getTourId() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < altNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %10s", k+1, altNames[k] ); + modelLogger.info(String.format("%-15s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %10s", chosenComposition, altNames[chosenComposition-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + jointTourComposition.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + jointTourComposition.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosenComposition ); + + // write UEC calculation results to separate model specific log file + jointTourComposition.logUECResults( modelLogger, loggingHeader ); + + } + + + jointTours[i].setJointTourComposition( chosenComposition ); + //jointTourChoiceFreq[chosenFreqAlt][chosenComposition]++; + + + jointTourParticipation( jointTours[i] ); + + } + + } + + } + catch ( Exception e ) { + logger.error( String.format( "error joint tour choices model for hhId=%d.", household.getHhId() )); + throw new RuntimeException(); + } + + household.setJtfRandomCount( household.getHhRandomCount() ); + + } + + + private void jointTourParticipation( TourIf jointTour ) { + + // get the Household object for this joint tour + HouseholdIf household = dmuObject.getHouseholdObject(); + + // get the array of Person objects for this hh + PersonIf[] persons = household.getPersons(); + + // define an ArrayList to hold indices of person objects participating in the joint tour + ArrayList jointTourPersonList = null; + + + // make sure each joint tour has a valid composition before going to the next one. + boolean validParty = false; + + + int adults = 0; + int children = 0; + + Logger modelLogger = tourFreq; + + while ( !validParty ) { + + adults = 0; + children = 0; + + jointTourPersonList = new ArrayList(); + + String separator = ""; + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + String loggingHeader = ""; + + for (int p = 1; p < persons.length; p++) { + + PersonIf person = persons[p]; + jointTour.setPersonObject( persons[p] ); + + if ( household.getDebugChoiceModels() ) { + decisionMakerLabel = String.format ( "HH=%d, hhSize=%d, PersonNum=%d, PersonType=%s, tourId=%d.", household.getHhId(), household.getHhSize(), person.getPersonNum(), person.getPersonType(), jointTour.getTourId() ); + household.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + + // if person type is inconsistent with tour composition, person's participation is by definition no, + // so skip making the choice and go to next person + switch ( jointTour.getJointTourComposition() ) { + + // adults only in joint tour + case 1: + if ( persons[p].getPersonIsAdult() == 1 ) { + + // write debug header + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Adult Party Joint Tour Participation Choice Model:" ); + jointTourParticipation.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + + jointTourParticipation.computeUtilities ( dmuObject, dmuObject.getDmuIndexValues() ); + // get the random number from the household + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available adults only joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] altNames = jointTourParticipation.getAlternativeNames(); + + double[] utilities = jointTourParticipation.getUtilities(); + double[] probabilities = jointTourParticipation.getProbabilities(); + + modelLogger.info("HHID: " + household.getHhId() + ", HHSize: " + household.getHhSize() + ", tourId: " + jointTour.getTourId() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < altNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %13s", k+1, altNames[k] ); + modelLogger.info(String.format("%-18s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %13s", chosen, altNames[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + jointTourParticipation.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + jointTourParticipation.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + jointTourParticipation.logUECResults( modelLogger, loggingHeader ); + + } + + + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + adults++; + } + } + break; + + // children only in joint tour + case 2: + if ( persons[p].getPersonIsAdult() == 0 ) { + + // write debug header + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Child Party Joint Tour Participation Choice Model:" ); + jointTourParticipation.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + + jointTourParticipation.computeUtilities ( dmuObject, dmuObject.getDmuIndexValues() ); + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available children only joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] altNames = jointTourParticipation.getAlternativeNames(); + + double[] utilities = jointTourParticipation.getUtilities(); + double[] probabilities = jointTourParticipation.getProbabilities(); + + modelLogger.info("HHID: " + household.getHhId() + ", HHSize: " + household.getHhSize() + ", tourId: " + jointTour.getTourId() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < altNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %13s", k+1, altNames[k] ); + modelLogger.info(String.format("%-18s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %13s", chosen, altNames[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + jointTourParticipation.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + jointTourParticipation.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + jointTourParticipation.logUECResults( modelLogger, loggingHeader ); + + } + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + children++; + } + } + break; + + // mixed, adults and children in joint tour + case 3: + IndexValues index = dmuObject.getDmuIndexValues(); + + // write debug header + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Mixed Party Joint Tour Participation Choice Model:" ); + jointTourParticipation.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + + jointTourParticipation.computeUtilities ( dmuObject, index ); + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( jointTourParticipation.getAvailabilityCount() > 0 ) + chosen = jointTourParticipation.getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, person p=%d, no available mixed adult/children joint tour participation alternatives to choose from in choiceModelApplication.", jointTour.getHhId(), p ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + String[] altNames = jointTourParticipation.getAlternativeNames(); + + double[] utilities = jointTourParticipation.getUtilities(); + double[] probabilities = jointTourParticipation.getProbabilities(); + + modelLogger.info("HHID: " + household.getHhId() + ", HHSize: " + household.getHhSize() + ", tourId: " + jointTour.getTourId() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for( int k=0; k < altNames.length; k++ ){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %13s", k+1, altNames[k] ); + modelLogger.info(String.format("%-18s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %13s", chosen, altNames[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + jointTourParticipation.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + jointTourParticipation.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + jointTourParticipation.logUECResults( modelLogger, loggingHeader ); + + } + + // particpate is alternative 1, not participating is alternative 2. + if ( chosen == 1 ) { + jointTourPersonList.add((byte)p); + if ( persons[p].getPersonIsAdult() == 1 ) + adults++; + else + children++; + } + break; + + } + + } + + + // done with all persons, so see if the chosen participation is a valid composition, and if not, repeat the participation choice. + switch ( jointTour.getJointTourComposition() ) { + + case 1: + if ( adults > 1 && children == 0 ) + validParty = true; + break; + + case 2: + if ( adults == 0 && children > 1 ) + validParty = true; + break; + + case 3: + if ( adults > 0 && children > 0 ) + validParty = true; + break; + + } + + } // end while + + + // create an array of person indices for participation in the tour + byte[] personNums = new byte[jointTourPersonList.size()]; + for ( int i=0; i < personNums.length; i++ ) + personNums[i] = jointTourPersonList.get(i); + jointTour.setPersonNumArray( personNums ); + + + if ( household.getDebugChoiceModels() ) { + for ( int i=0; i < personNums.length; i++ ) { + PersonIf person = household.getPersons()[personNums[i]]; + String decisionMakerLabel = String.format ( "Person in Party, HH=%d, hhSize=%d, PersonNum=%d, PersonType=%s, tourId=%d.", household.getHhId(), household.getHhSize(), person.getPersonNum(), person.getPersonType(), jointTour.getTourId() ); + household.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + } + + // create a key to use for a frequency map for "JointTourPurpose_Composition_NumAdults_NumChildren" + //String key = String.format( "%s_%d_%d_%d", jointTour.getTourPurpose(), jointTour.getJointTourComposition(), adults, children ); + + //int value = 0; + //if ( partySizeFreq.containsKey( key ) ) + //value = partySizeFreq.get( key ); + //partySizeFreq.put( key, ++value ); + + } + + + + + /** + * creates the tour objects in the Household object given the chosen joint tour frequency alternative. + * @param chosenAlt + */ + private void createJointTours ( HouseholdIf household, int chosenAlt ) { + Object[] t1Data = null; + Object[] t2Data = null; + + + // joint tours in a multiple tour set are created in a specific order according to the following hierarchy: + // maint, shop, discr, eat, visit + + switch ( chosenAlt ) { + + // no joint tours + case 1: + // call a method to create a joint tour array with zero elements. A zero element array indicates a 0_tours choice was made. + // as opposed to a null jointTours array which indicates that the household was not eligible to make any joint tours. + break; + + // 1 joint shop tour + case 2: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; break; + // 1 joint maint tour + case 3: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; break; + // 1 joint eat tour + case 4: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint visit tour + case 5: t1Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint disc tour + case 6: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint shop tour + case 7: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; break; + // 1 joint shop tour and 1 joint maint tour + case 8: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; break; + // 1 joint shop tour and 1 joint eat tour + case 9: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint shop tour and 1 joint visit tour + case 10: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint shop tour and 1 joint discr tour + case 11: t1Data = new Object[] {shoppingPurposeIndex,shoppingPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint maint tour + case 12: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {maintPurposeIndex,maintPurposeString}; break; + // 1 joint maint tour and 1 joint eat tour + case 13: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint maint tour and 1 joint visit tour + case 14: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint maint tour and 1 joint discr tour + case 15: t1Data = new Object[] {maintPurposeIndex,maintPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + // 2 joint eat tour + case 16: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 1 joint eat tour and 1 joint visit tour + case 17: t1Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint eat tour and 1 joint discr tour + case 18: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; + t2Data = new Object[] {eatOutPurposeIndex,eatOutPurposeString}; break; + // 2 joint visit tour + case 19: t1Data = new Object[] {socialPurposeIndex,socialPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 1 joint visit tour and 1 joint discr tour + case 20: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; + t2Data = new Object[] {socialPurposeIndex,socialPurposeString}; break; + // 2 joint discr tour + case 21: t1Data = new Object[] {discrPurposeIndex,discrPurposeString}; + t2Data = new Object[] {discrPurposeIndex,discrPurposeString}; break; + + } + + //create tours + if (t1Data != null) { + if (t2Data == null) { + household.createJointTourArray(t1Data); + } else { + household.createJointTourArray(t1Data,t2Data); + } + } + + } + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/LocationChoiceTaskJppf.java b/src/java/com/pb/models/ctrampIf/jppf/LocationChoiceTaskJppf.java new file mode 100644 index 0000000..e5298c1 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/LocationChoiceTaskJppf.java @@ -0,0 +1,236 @@ +package com.pb.models.ctrampIf.jppf; + + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; + +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.jppf.MandatoryDestChoiceModel; + +import org.apache.log4j.Logger; +import org.jppf.node.protocol.DataProvider; +import org.jppf.node.protocol.AbstractTask; + + + +public class LocationChoiceTaskJppf extends AbstractTask { + + private static String VERSION = "Task.1.0.3"; + + private transient HashMap propertyMap; + private transient MatrixDataServerIf ms; + private transient HouseholdDataManagerIf hhDataManager; + private transient ModelStructure modelStructure; + private transient String tourCategory; + private transient TazDataIf tazDataManager; + private transient DestChoiceSize dcSizeObj; + private transient String dcUecFileName; + private transient String soaUecFileName; + private transient int soaSampleSize; + private transient String modeChoiceUecFileName; + private transient CtrampDmuFactoryIf dmuFactory; + private transient String restartModelString; + + private int iteration; + private int startIndex; + private int endIndex; + private int taskIndex = -1; + + + + public LocationChoiceTaskJppf( int taskIndex, int startIndex, int endIndex, int iteration ) { + this.startIndex = startIndex; + this.endIndex = endIndex; + this.taskIndex = taskIndex; + this.iteration = iteration; + } + + + public void run() { + + long startTime = System.currentTimeMillis(); + + String threadName = null; + try { + threadName = java.net.InetAddress.getLocalHost().getHostName() + " " + Thread.currentThread().getName(); + } catch (UnknownHostException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + Logger logger = Logger.getLogger( this.getClass() ); + + try { + DataProvider dataProvider = getDataProvider(); + + this.propertyMap = (HashMap) dataProvider.getParameter("propertyMap"); + this.ms = (MatrixDataServerIf) dataProvider.getParameter("ms"); + this.modelStructure = (ModelStructure) dataProvider.getParameter("modelStructure"); + this.tourCategory = (String) dataProvider.getParameter("tourCategory"); + this.tazDataManager = (TazDataIf) dataProvider.getParameter("tazDataManager"); + this.hhDataManager = (HouseholdDataManagerIf) dataProvider.getParameter("householdDataManager"); + this.dcSizeObj = (DestChoiceSize) dataProvider.getParameter("dcSizeObj"); + this.dcUecFileName = (String) dataProvider.getParameter("dcUecFileName"); + this.soaUecFileName = (String) dataProvider.getParameter("soaUecFileName"); + this.soaSampleSize = (Integer) dataProvider.getParameter("soaSampleSize"); + this.modeChoiceUecFileName = (String) dataProvider.getParameter("modeChoiceUecFileName"); + this.dmuFactory = (CtrampDmuFactoryIf) dataProvider.getParameter("dmuFactory"); + this.restartModelString = (String) dataProvider.getParameter("restartModelString"); + + } catch (Exception e) { + e.printStackTrace(); + } + + + HouseholdChoiceModelsManager hhModelManager = HouseholdChoiceModelsManager.getInstance( propertyMap, restartModelString, modelStructure, tazDataManager, dmuFactory ); + hhModelManager.clearHhModels(); + + + + // get the factory object used to create and recycle dcModel objects. + DestChoiceModelManager modelManager = DestChoiceModelManager.getInstance(); + + // one of tasks needs to initialize the manager object by passing attributes needed to create a destination choice model object. + modelManager.factorySetup( propertyMap, ms, modelStructure, tourCategory, tazDataManager, dcSizeObj, dcUecFileName, soaUecFileName, soaSampleSize, modeChoiceUecFileName, dmuFactory, restartModelString ); + + + + // get a dcModel object from manager, which either creates one or returns one for re-use. + MandatoryDestChoiceModel dcModel = modelManager.getDcModelObject( taskIndex, iteration ); + + // reset the dc size object so scaled size values are used for iteration >= 1. + dcModel.setDcSize ( dcSizeObj, iteration ); + + long setup1 = 0; + long setup2 = 0; + long setup3 = 0; + long setup4 = 0; + long lsTime = 0; + long soaTime = 0; + long totTime = 0; + +// long[][] filterCount = new long[dcModel.getFilterCount().length][dcModel.getFilterCount()[0].length]; +// long[][] expressionCount = new long[dcModel.getExpressionCount().length][dcModel.getExpressionCount()[0].length]; +// long[][] coeffCount = new long[dcModel.getCoeffCount().length][dcModel.getCoeffCount()[0].length]; + long cmUecTime = 0; + long cmOtherTime = 0; + long lsTotalTime = 0; + + HouseholdIf[] householdArray = null; + + int i = -1; + try { + + setup1 = System.currentTimeMillis() - startTime; + + householdArray = hhDataManager.getHhArray( startIndex, endIndex ); + + setup2 = System.currentTimeMillis() - startTime; + + for ( i=0; i < householdArray.length; i++ ) { + dcModel.applyWorkSchoolLocationChoice ( householdArray[i] ); + lsTime += dcModel.getLogsumTime(); + soaTime += dcModel.getSoaTime(); + totTime += dcModel.getTotTime(); + + cmUecTime += dcModel.getCmUecTime(); + cmOtherTime += dcModel.getCmOtherTime(); + lsTotalTime += dcModel.getLsTotalTime(); +// long[][] counts = dcModel.getFilterCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// filterCount[j][k] += counts[j][k]; +// counts = dcModel.getExpressionCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// expressionCount[j][k] += counts[j][k]; +// counts = dcModel.getCoeffCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// coeffCount[j][k] += counts[j][k]; + } + + setup3 = System.currentTimeMillis() - startTime; + + hhDataManager.setHhArray( householdArray, startIndex ); + + setup4 = System.currentTimeMillis() - startTime; + + } + catch ( Exception e ) { + if ( i >= 0 && i < householdArray.length ) + System.out.println ( String.format("exception caught in taskIndex=%d applying dc model for i=%d, hhId=%d, startIndex=%d.", taskIndex, i, householdArray[i].getHhId(), startIndex) ); + else + System.out.println ( String.format("exception caught in taskIndex=%d applying dc model for i=%d, startIndex=%d.", taskIndex, i, startIndex) ); + System.out.println ( "Exception caught:" ); + e.printStackTrace(); + System.out.println ( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException( e ); + } + + + long total = (System.currentTimeMillis() - startTime) / 1000; + logger.info( "task=" + taskIndex + " finished, thread=" + threadName + ", " + startTime + ", " + System.currentTimeMillis() + "." ); + logger.info( "task=" + taskIndex + ", setup=" + setup1 + ", getHhs=" + (setup2 - setup1) + ", processHhs=" + (setup3 - setup2) + ", putHhs=" + (setup4 - setup3) + ", total=" + total + "." ); + logger.info( "task=" + taskIndex + ", lsTime=" + (lsTime/1000000) + ", soaTime=" + (soaTime/1000000) + ", totTime=" + (totTime/1000000) + ", cmUecTime=" + (cmUecTime/1000000) + ", cmOtherTime=" + (cmOtherTime/1000000) + ", lsTotalTime=" + (lsTotalTime/1000000) + "." ); + +// writeCounts("filter", filterCount); +// writeCounts("expression", expressionCount); +// writeCounts("coeff", coeffCount); + + String resultString = "result for thread=" + threadName + ", task=" + taskIndex + ", startIndex=" + startIndex + "endIndex=" + endIndex + ", total=" + total + "secs for task."; + setResult( (T)resultString ); + + modelManager.returnDcModelObject( dcModel, taskIndex, startIndex, endIndex ); + + } + + private void writeCounts(String countType, long[][] count){ + + FileWriter writer; + PrintWriter outStream = null; + String fileName = "task" + taskIndex + "_" + countType + ".csv"; + try { + writer = new FileWriter(new File(fileName)); + outStream = new PrintWriter(new BufferedWriter(writer)); + + String headerString = "e"; + for ( int k=0; k < count[0].length; k++ ) + headerString += ( ", a" + (k+1) ); + outStream.println( headerString ); + + for ( int j=0; j < count.length; j++ ){ + String valueString = String.valueOf((j+1)); + for ( int k=0; k < count[j].length; k++ ) + valueString += ( "," + count[j][k] ); + outStream.println( valueString ); + } + + outStream.close(); + } + catch (IOException e) { + System.out.println( String.format("Exception occurred writing task performance file: %s.", fileName) ); + throw new RuntimeException(e); + } + + } + + public String getId() { + return Integer.toString(taskIndex); + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/MandatoryDestChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/MandatoryDestChoiceModel.java new file mode 100644 index 0000000..05ea64f --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/MandatoryDestChoiceModel.java @@ -0,0 +1,627 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Random; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.ResourceBundle; + + +import com.pb.common.calculator.VariableTable; +import com.pb.common.util.IndexSort; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DcSoaDMU; +import com.pb.models.ctrampIf.DestChoiceDMU; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.jppf.DestinationSampleOfAlternativesModel; +import com.pb.models.ctrampIf.jppf.ModeChoiceModel; +import com.pb.common.newmodel.ChoiceModelApplication; +import org.apache.log4j.Logger; + +public class MandatoryDestChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(MandatoryDestChoiceModel.class); + private transient Logger dcManLogger = Logger.getLogger("tourDcMan"); + + + private static final String PROPERTIES_MANDATORY_RUN_WORK = "UsualWorkAndSchoolLocationChoice.RunFlag.Work"; + private static final String PROPERTIES_MANDATORY_RUN_UNIVERSITY = "UsualWorkAndSchoolLocationChoice.RunFlag.University"; + private static final String PROPERTIES_MANDATORY_RUN_SCHOOL = "UsualWorkAndSchoolLocationChoice.RunFlag.School"; + + private static final int DC_DATA_SHEET = 0; + + + private String tourCategory; + private ModelStructure modelStructure; + + private String[] tourPurposeList; + private HashMap purposeModelIndexMap; + + private TourModeChoiceDMU mcDmuObject; + private DestChoiceDMU dcDmuObject; + private DcSoaDMU dcSoaDmuObject; + + private ModeChoiceModel mcModel; + private DestinationSampleOfAlternativesModel dcSoaModel; + + // A ChoiceModelApplication object and modeAltsAvailable[] is needed for each purpose + private ChoiceModelApplication dcModel[]; + + private int[] sampleValues; + + private boolean runWorkTours; + private boolean runUnivTours; + private boolean runSchoolTours; + + private int numberOfSubzones; + + private int modelIndex; + private int shadowPricingIteration; + + private long lsTime = 0; + private long soaTime = 0; + private long totTime = 0; + +// private long[][] filterCount = null; +// private long[][] expressionCount = null; +// private long[][] coeffCount = null; + private long cmUecTime; + private long cmOtherTime; + private long lsTotalTime; + + + public MandatoryDestChoiceModel( int index, HashMap propertyMap, ModelStructure modelStructure, String tourCategory, TazDataIf tazDataManager, DestChoiceSize dcSizeObj, String dcUecFileName, String soaUecFile, int soaSampleSize, String modeChoiceUecFile, CtrampDmuFactoryIf dmuFactory ){ + + // set the model structure and the tour purpose list + this.modelStructure = modelStructure; + this.tourCategory = tourCategory; + + modelIndex = index; + + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + dcDmuObject = dmuFactory.getDestChoiceDMU(); + + dcSoaDmuObject = dmuFactory.getDcSoaDMU(); + + dcDmuObject.setDestChoiceSize(dcSizeObj); + dcSoaDmuObject.setDestChoiceSizeObject(dcSizeObj); + + + // create an array of ChoiceModelApplication objects for each choice purpose + setupDestChoiceModelArrays( propertyMap, dcUecFileName, modeChoiceUecFile, soaUecFile, soaSampleSize, dcSizeObj, tazDataManager ); + + shadowPricingIteration = 0; + + } + + private void setupDestChoiceModelArrays( HashMap propertyMap, String dcUecFileName, String modeChoiceUecFile, String soaUecFile, int soaSampleSize, DestChoiceSize dcSizeObj, TazDataIf tazDataManager ) { + + tourPurposeList = modelStructure.getDcModelPurposeList( this.tourCategory ); + + numberOfSubzones = tazDataManager.getNumberOfSubZones(); + + + // create the mode choice model + mcModel = new ModeChoiceModel( propertyMap, modelStructure, tourCategory, mcDmuObject, tazDataManager); +// filterCount = new long[mcModel.getFilterCount().length][mcModel.getFilterCount()[0].length]; +// expressionCount = new long[mcModel.getExpressionCount().length][mcModel.getExpressionCount()[0].length]; +// coeffCount = new long[mcModel.getCoeffCount().length][mcModel.getCoeffCount()[0].length]; + + // these flags are useful in calibration to limit the number of usual work and school location choices made + // to speed up calibration model runs. + if ( tourCategory.equalsIgnoreCase( ModelStructure.MANDATORY_CATEGORY ) ) { + + String propertyValue = ""; + + runWorkTours = false; + propertyValue = propertyMap.get( PROPERTIES_MANDATORY_RUN_WORK ); + if ( propertyValue != null ) + runWorkTours = propertyValue.equalsIgnoreCase("true"); + + runUnivTours = false; + propertyValue = propertyMap.get( PROPERTIES_MANDATORY_RUN_UNIVERSITY ); + if ( propertyValue != null ) + runUnivTours = propertyValue.equalsIgnoreCase("true"); + + runSchoolTours = false; + propertyValue = propertyMap.get( PROPERTIES_MANDATORY_RUN_SCHOOL ); + if ( propertyValue != null ) + runSchoolTours = propertyValue.equalsIgnoreCase("true"); + + } + + + // create a sample of alternatives choice model object for use in selecting a sample + // of all possible destination choice alternatives. + dcSoaModel = new DestinationSampleOfAlternativesModel( soaUecFile, soaSampleSize, propertyMap, modelStructure, tourCategory, tazDataManager, dcSizeObj, dcSoaDmuObject ); + + + // get the number of purposes and declare the array dimension to be this size. + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + int maxUecIndex = 0; + for ( String purposeName : tourPurposeList ) { + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + purposeModelIndexMap.put( purposeName, uecIndex ); + if ( uecIndex > maxUecIndex ) + maxUecIndex = uecIndex; + } + + dcModel = new ChoiceModelApplication[maxUecIndex+1]; + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + for ( int m : purposeModelIndexMap.values() ) { + dcModel[m] = new ChoiceModelApplication ( dcUecFileName, m, DC_DATA_SHEET, propertyMap, (VariableTable)dcDmuObject ); + } + + sampleValues = new int[soaSampleSize]; + + } + + + /** + * This method is called if a shadow pricing methodology is applied to reset the scaled size terms in objects that reference them. + */ + public void setDcSize ( DestChoiceSize dcSizeObj, int currentShadowPriceIteration ) { + + // if a dcModel object is being recycled by multiple tasks, only need to reset size object once per iteration. + if ( currentShadowPriceIteration > shadowPricingIteration ) { + + dcDmuObject.setDestChoiceSize(dcSizeObj); + dcSoaDmuObject.setDestChoiceSizeObject(dcSizeObj); + + dcSoaModel.setDcSizeForSampleOfAlternatives( tourPurposeList, dcSizeObj ); + shadowPricingIteration++; + + } + + } + + + + public void applyWorkSchoolLocationChoice( HouseholdIf hh ) { + + lsTime = 0; + soaTime = 0; + totTime = 0; + + cmUecTime = 0; + cmOtherTime = 0; + lsTotalTime = 0; +// for (int i=0; i < filterCount.length; i++ ){ +// Arrays.fill(filterCount[i], 0); +// Arrays.fill(expressionCount[i], 0); +// Arrays.fill(coeffCount[i], 0); +// } + + long totCheck = System.nanoTime(); + + if ( hh.getDebugChoiceModels() ) { + String label = String.format( "Pre Work/School Location Choice HHId=%d Object", hh.getHhId() ); + hh.logHouseholdObject( label, dcManLogger ); + } + + + // declare these variables here so their values can be logged if a RuntimeException occurs. + int i = -1; + int purposeIndex = -1; + String purposeName = ""; + + + PersonIf[] persons = hh.getPersons(); + + for ( i=1; i < persons.length; i++ ) { + + ArrayList dcPurposeList = new ArrayList(); + + PersonIf p = persons[i]; + + // get a list of DC purpose names for this person based on the standard person types that make mandatory tours: + if ( p.getPersonIsPreschoolChild() == 1 || p.getPersonIsStudentNonDriving() == 1 || p.getPersonIsStudentDriving() == 1 ) { + if ( runSchoolTours ) + dcPurposeList.add( modelStructure.getSchoolPurpose( p.getAge() ) ); + if ( runWorkTours && p.getPersonIsStudentDriving() == 1 && p.getPersonIsWorker() == 1 ) + dcPurposeList.add( modelStructure.getWorkPurposeFromOccupation( p.getPersonWorkerOccupation() )); + } + else if ( p.getPersonIsUniversityStudent() == 1 ) { + if ( runUnivTours ) + dcPurposeList.add( modelStructure.getUniversityPurpose() ); + if ( runWorkTours && p.getPersonIsWorker() == 1 ) + dcPurposeList.add( modelStructure.getWorkPurposeFromOccupation( p.getPersonWorkerOccupation() )); + } + else if ( ( p.getPersonIsPartTimeWorker() == 1 || p.getPersonIsFullTimeWorker() == 1 ) ) { + if ( runWorkTours ) + dcPurposeList.add( modelStructure.getWorkPurposeFromOccupation( p.getPersonWorkerOccupation() )); + } + + + if ( hh.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", p.getHouseholdObject().getHhId(), p.getPersonNum(), p.getPersonType() ); + + Logger modelLogger = null; + modelLogger = dcManLogger; + + hh.logPersonObject( decisionMakerLabel, modelLogger, p ); + } + + + int choiceNum = 0; + for ( String dcPurposeName : dcPurposeList ) { + + purposeName = dcPurposeName; + purposeIndex = modelStructure.getDcModelPurposeIndex( purposeName ); + + int chosen = -1; + try { + + int homeTaz = hh.getHhTaz(); + int origTaz = homeTaz; + + // update the MC dmuObject for this person + mcDmuObject.setHouseholdObject( hh ); + mcDmuObject.setPersonObject( p ); + mcDmuObject.setTourObject( p.makeDefaultTour( modelStructure.getPrimaryPurposeIndex( modelStructure.getPrimaryPurposeString(purposeName) ) ) ); // make a Tour object for use by the MC DMU for work/school location choice MC logsum + mcDmuObject.setDmuIndexValues( hh.getHhId(), hh.getHhTaz(), origTaz, 0, hh.getDebugChoiceModels() ); + + // update the DC dmuObject for this person + dcDmuObject.setHouseholdObject( hh ); + dcDmuObject.setPersonObject( p ); + dcDmuObject.setDmuIndexValues( hh.getHhId(), homeTaz, origTaz, 0 ); + + // get the work location alternative chosen from the sample + chosen = selectLocationFromSampleOfAlternatives( dcDmuObject, dcSoaDmuObject, mcDmuObject, null, p, purposeName, purposeIndex, ++choiceNum ); + + } + catch (RuntimeException e) { + logger.fatal( String.format("Exception caught in dcModel selecting work or school location for i=%d, hh.hhid=%d, person i=%d, in %s choice, purposeIndex=%d, purposeName=%s", i, hh.getHhId(), i, tourCategory, purposeIndex, purposeName ) ); + logger.fatal( "Exception caught:", e ); + logger.fatal( "Throwing new RuntimeException() to terminate." ); + throw new RuntimeException(); + } + + // get zone, subzone from DC alternative + int chosenDestAlt = (chosen-1)/numberOfSubzones + 1; + int chosenShrtWlk = chosen - (chosenDestAlt-1)*numberOfSubzones - 1; + + + + // set chosen values in person object - university and school are saved as school locations + if ( modelStructure.getDcModelPurposeIsWorkPurpose( purposeName ) ) { + p.setWorkLoc( chosenDestAlt ); + p.setWorkLocSubzone( chosenShrtWlk ); + } + else if ( modelStructure.getDcModelPurposeIsSchoolPurpose( purposeName ) ) { + p.setSchoolLoc( chosenDestAlt ); + p.setSchoolLocSubzone( chosenShrtWlk ); + } + else if ( modelStructure.getDcModelPurposeIsUniversityPurpose( purposeName ) ) { + p.setSchoolLoc( chosenDestAlt ); + p.setSchoolLocSubzone( chosenShrtWlk ); + } + + } + + } + + totTime += (System.nanoTime() - totCheck); + } + + + + + + private int selectLocationFromSampleOfAlternatives( DestChoiceDMU dcDmuObject, DcSoaDMU dcSoaDmuObject, TourModeChoiceDMU mcDmuObject, TourIf tour, PersonIf person, String purposeName, int purposeIndex, int choiceNum ) { + + int uecIndex = modelStructure.getDcUecIndexForPurpose( purposeName ); + + HouseholdIf household = dcDmuObject.getHouseholdObject(); + + long soaCheck = System.nanoTime(); + + // compute the sample of alternatives set for the person + dcSoaModel.computeDestinationSampleOfAlternatives( dcSoaDmuObject, null, person, purposeName, purposeIndex ); + + soaTime += (System.nanoTime() - soaCheck); + + // get sample of locations and correction factors for sample + int numUniqueAltsInSample = dcSoaModel.getNumUniqueAlts(); + int[] finalSample = dcSoaModel.getSampleOfAlternatives(); + float[] sampleCorrectionFactors = dcSoaModel.getSampleOfAlternativesCorrections(); + + + + + int numAlts = dcModel[uecIndex].getNumberOfAlternatives(); + + boolean[] destAltsAvailable = new boolean[numAlts+1]; + int[] destAltsSample = new int[numAlts+1]; + + // set the destAltsAvailable array to true for all destination choice alternatives for each purpose + for (int k=0; k <= numAlts; k++) + destAltsAvailable[k] = false; + + // set the destAltsSample array to 1 for all destination choice alternatives for each purpose + for (int k=0; k <= numAlts; k++) + destAltsSample[k] = 0; + + + + String tourPrimaryPurpose = ""; + + + // set tour origin taz/subzone and start/end times for calculating mode choice logsum + int origTaz = -1; + int origSubz = -1; + int tourDepart = -1; + int tourArrive = -1; + Logger modelLogger = null; + if ( modelStructure.getPrimaryPurposeString(purposeName).equalsIgnoreCase( ModelStructure.WORK_PRIMARY_PURPOSE_NAME ) ) { + tourPrimaryPurpose = ModelStructure.WORK_PRIMARY_PURPOSE_NAME; + tourDepart = modelStructure.getWorkLocationDefaultDepartPeriod(); + tourArrive = modelStructure.getWorkLocationDefaultArrivePeriod(); + origTaz = household.getHhTaz(); + origSubz = household.getHhWalkSubzone(); + modelLogger = dcManLogger; + } + else if ( modelStructure.getPrimaryPurposeString(purposeName).equalsIgnoreCase( ModelStructure.UNIVERSITY_PURPOSE_NAME ) ) { + tourPrimaryPurpose = ModelStructure.UNIVERSITY_PRIMARY_PURPOSE_NAME; + tourDepart = modelStructure.getUniversityLocationDefaultDepartPeriod(); + tourArrive = modelStructure.getUniversityLocationDefaultArrivePeriod(); + origTaz = household.getHhTaz(); + origSubz = household.getHhWalkSubzone(); + modelLogger = dcManLogger; + } + else if ( modelStructure.getPrimaryPurposeString(purposeName).equalsIgnoreCase( ModelStructure.SCHOOL_PURPOSE_NAME ) ) { + tourPrimaryPurpose = ModelStructure.SCHOOL_PRIMARY_PURPOSE_NAME; + tourDepart = modelStructure.getSchoolLocationDefaultDepartPeriod(); + tourArrive = modelStructure.getSchoolLocationDefaultArrivePeriod(); + origTaz = household.getHhTaz(); + origSubz = household.getHhWalkSubzone(); + modelLogger = dcManLogger; + } + + + // determine the logsum array index into which the computed values will be stored + int logsumIndex = modelStructure.getPeriodCombinationIndex( tourDepart, tourArrive ); + + + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if ( household.getDebugChoiceModels() ) { + choiceModelDescription = String.format ( "Tour Mode Choice Logsum calculation for %s Location Choice", tourPrimaryPurpose ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s", household.getHhId(), person.getPersonNum(), person.getPersonType() ); + loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + } + + + // for the destinations and sub-zones in the sample, compute mc logsums and save in DC dmuObject. + // also save correction factor and set availability and sample value for the sample alternative to true. 1, respectively. + for (int i=1; i <= numUniqueAltsInSample; i++) { + + int d = (finalSample[i]-1)/numberOfSubzones + 1; + int w = finalSample[i] - (d-1)*numberOfSubzones - 1; + + + // set the zone, walk subzone, start and end time values for the mcDmuObject and calculate the logsum. + mcDmuObject.setTourOrigTaz( origTaz ); + mcDmuObject.setTourOrigWalkSubzone( origSubz ); + mcDmuObject.setTourDestTaz( d ); + mcDmuObject.setTourDestWalkSubzone( w ); + mcDmuObject.setTourDepartPeriod( tourDepart ); + mcDmuObject.setTourArrivePeriod( tourArrive ); + mcDmuObject.setDmuIndexValues( household.getHhId(), d, origTaz, d, household.getDebugChoiceModels() ); + + //create TVPB for tour mode choice model + mcModel.setTVPBValues(mcDmuObject, tourPrimaryPurpose); + + if ( household.getDebugChoiceModels() ) { + household.logTourObject( loggingHeader, modelLogger, person, mcDmuObject.getTourObject() ); + } + + long lsCheck = System.nanoTime(); + + // get the mode choice logsum for the destination choice sample alternative + double logsum = mcModel.getModeChoiceLogsum( mcDmuObject, tourPrimaryPurpose, modelLogger, choiceModelDescription, decisionMakerLabel ); + + lsTime += (System.nanoTime() - lsCheck); + + cmUecTime += mcModel.getCmUecTime(); + cmOtherTime += mcModel.getCmOtherTime(); + lsTotalTime += mcModel.getLsTotalTime(); +// long[][] counts = mcModel.getFilterCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// filterCount[j][k] += counts[j][k]; +// counts = mcModel.getExpressionCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// expressionCount[j][k] += counts[j][k]; +// counts = mcModel.getCoeffCount(); +// for ( int j=0; j < counts.length; j++ ) +// for ( int k=0; k < counts[j].length; k++ ) +// coeffCount[j][k] += counts[j][k]; + + // set logsum value in DC dmuObject for the logsum index, sampled zone and subzone. + dcDmuObject.setMcLogsum ( logsumIndex, d, w, logsum ); + + // set sample of alternatives correction factor used in destination choice utility for the sampled alternative. + dcDmuObject.setDcSoaCorrections( d, w, sampleCorrectionFactors[i] ); + + // set availaibility and sample values for the purpose, dcAlt. + destAltsAvailable[finalSample[i]] = true; + destAltsSample[finalSample[i]] = 1; + + } + + + + // log headers to traceLogger if the person making the destination choice is from a household requesting trace information + if ( household.getDebugChoiceModels() ) { + + // null tour means the DC is a mandatory usual location choice + choiceModelDescription = String.format ( "Usual Location Choice Model for: Purpose=%s", tourPrimaryPurpose ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourNum=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), choiceNum ); + + modelLogger.info(" "); + modelLogger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + modelLogger.info( "Usual Location Choice Model for: Purpose=" + tourPrimaryPurpose + + ", Person Num: "+person.getPersonNum() + ", Person Type: "+person.getPersonType() + ", TourNum=" + choiceNum ); + + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + dcModel[uecIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + // compute destination choice proportions and choose alternative + dcModel[uecIndex].computeUtilities ( dcDmuObject, dcDmuObject.getDmuIndexValues(), destAltsAvailable, destAltsSample ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( dcModel[uecIndex].getAvailabilityCount() > 0 ) { + chosen = dcModel[uecIndex].getChoiceResult( rn ); + } + else { + logger.error ( String.format( "Exception caught for HHID=%d, PersonNum=%d, no available %s destination choice alternatives to choose from in choiceModelApplication.", dcDmuObject.getHouseholdObject().getHhId(), dcDmuObject.getPersonObject().getPersonNum(), tourPrimaryPurpose ) ); + } + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() || chosen < 0 ) { + + double[] utilities = dcModel[uecIndex].getUtilities(); + double[] probabilities = dcModel[uecIndex].getProbabilities(); + boolean[] availabilities = dcModel[uecIndex].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("--------------------- -------------- -------------- -------------- --------------"); + + // copy the values of the sample to an array that can be sorted for logging purposes + for (int i=1; i <= numUniqueAltsInSample; i++) + sampleValues[i-1] = finalSample[i]; + for (int i=numUniqueAltsInSample; i < sampleValues.length; i++) + sampleValues[i] = Integer.MAX_VALUE; + int[] sortedSampleValueIndices = IndexSort.indexSort( sampleValues ); + + double cumProb = 0.0; + int selectedIndex = -1; + for(int j=1; j <= numUniqueAltsInSample; j++){ + + int k = sortedSampleValueIndices[j-1]; + int alt = finalSample[k+1]; + + if ( alt == chosen ) + selectedIndex = j; + + int d = ( alt-1) / numberOfSubzones + 1; + int w = alt - (d-1)*numberOfSubzones - 1; + cumProb += probabilities[alt-1]; + String altString = String.format( "%-3d %5d %5d %5d", j, alt, d, w ); + modelLogger.info(String.format("%-21s%15s%18.6e%18.6e%18.6e", altString, availabilities[alt], utilities[alt-1], probabilities[alt-1], cumProb)); + } + + if ( chosen >= 0 ) { + modelLogger.info(" "); + int d = (chosen-1)/numberOfSubzones + 1; + int w = chosen - (d-1)*numberOfSubzones - 1; + String altString = String.format( "%-3d %5d %5d %5d", selectedIndex, chosen, d, w ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + } + modelLogger.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + modelLogger.info(" "); + + + + dcModel[uecIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + dcModel[uecIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + dcModel[uecIndex].logUECResults( modelLogger, loggingHeader ); + + + if ( chosen < 0 ) + System.exit(-1); + } + + return chosen; + + } + + /** + * @return total milliseconds accumulated computing MC Logsums for destination choice + */ + public long getLogsumTime() { + return lsTime; + } + + /** + * @return total milliseconds accumulated computing SOA probabilities for destination choice + */ + public long getSoaTime() { + return soaTime; + } + + /** + * @return total milliseconds accumulated computing destination choice + */ + public long getTotTime() { + return totTime; + } + + public int getProbCalcs() { + return dcSoaModel.getSoaProbabilitiesCalculationCount(); + } + + public int getModelIndex(){ + return modelIndex; + } + + public int getCurrentOrigTaz() { + return dcSoaModel.getCurrentOrigTaz(); + } + + +// public long[][] getFilterCount() { +// return filterCount; +// } +// public long[][] getExpressionCount() { +// return expressionCount; +// } +// public long[][] getCoeffCount() { +// return coeffCount; +// } + public long getCmUecTime() { + return cmUecTime; + } + public long getCmOtherTime() { + return cmOtherTime; + } + public long getLsTotalTime() { + return lsTotalTime; + } + + + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/ModeChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/ModeChoiceModel.java new file mode 100644 index 0000000..e3e8178 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/ModeChoiceModel.java @@ -0,0 +1,614 @@ +package com.pb.models.ctrampIf.jppf; + +import java.io.Serializable; +import java.util.*; + +import com.pb.cmap.tvpb.TapPair; +import com.pb.cmap.tvpb.TransitVirtualPathBuilder; +import com.pb.cmap.tvpb.Trip; +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; +import org.apache.log4j.Logger; +import com.pb.common.util.ResourceUtil; + +public class ModeChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(ModeChoiceModel.class); + private transient Logger tourMCManLogger = Logger.getLogger( "tourMcMan" ); + private transient Logger tourMCNonManLogger = Logger.getLogger( "tourMcNonMan" ); + + + public static final int MC_DATA_SHEET = 0; + public static final String PROPERTIES_UEC_TOUR_MODE_CHOICE = "UecFile.TourModeChoice"; + + + // A MyChoiceModelApplication object and modeAltsAvailable[] is needed for each purpose + private ChoiceModelApplication mcModel[]; + private TourModeChoiceDMU mcDmuObject; + + private String tourCategory; + private String[] tourPurposeList; + + private HashMap purposeModelIndexMap; + + private String[][] modeAltNames; + + private boolean saveUtilsProbsFlag=false; + +// private long[][] filterCount = null; +// private long[][] expressionCount = null; +// private long[][] coeffCount = null; + private long cmUecTime; + private long cmOtherTime; + private long mcLsTotalTime; + + TransitVirtualPathBuilder tvpb; + + public ModeChoiceModel( HashMap propertyMap, ModelStructure modelStructure, String tourCategory, CtrampDmuFactoryIf dmuFactory, TazDataIf tazDataManager){ + + this.tourCategory = tourCategory; + mcDmuObject = dmuFactory.getModeChoiceDMU(); + setupModeChoiceModelApplicationArray( propertyMap, modelStructure, tourCategory ); + + //create TVPB for trip mode choice UEC + tvpb = new TransitVirtualPathBuilder(propertyMap); + tvpb.setupTVPB(); + tvpb.setupModels(); + tvpb.setMTTData(tazDataManager.getMttData()); + } + + public ModeChoiceModel( HashMap propertyMap, ModelStructure modelStructure, String tourCategory, TourModeChoiceDMU mcDmuObject, TazDataIf tazDataManager){ + + this.tourCategory = tourCategory; + this.mcDmuObject = mcDmuObject; + setupModeChoiceModelApplicationArray( propertyMap, modelStructure, tourCategory ); + + //create TVPB for trip mode choice UEC + tvpb = new TransitVirtualPathBuilder(propertyMap); + tvpb.setupTVPB(); + tvpb.setupModels(); + tvpb.setMTTData(tazDataManager.getMttData()); + } + + + + private void setupModeChoiceModelApplicationArray( HashMap propertyMap, ModelStructure modelStructure, String tourCategory ) { + + logger.info( String.format( "setting up %s tour mode choice model.", tourCategory ) ); + + // locate the individual mandatory tour mode choice model UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + String mcUecFile = propertyMap.get( PROPERTIES_UEC_TOUR_MODE_CHOICE ); + mcUecFile = projectDirectory + mcUecFile; + + // default is to not save the tour mode choice utils and probs for each tour + String saveUtilsProbsString = propertyMap.get( CtrampApplication.PROPERTIES_SAVE_TOUR_MODE_CHOICE_UTILS ); + if ( saveUtilsProbsString != null ) { + if ( saveUtilsProbsString.equalsIgnoreCase( "true" ) ) + saveUtilsProbsFlag = true; + } + + + // get the number of purposes and declare the array dimension to be this size. + tourPurposeList = modelStructure.getDcModelPurposeList( tourCategory ); + + // create a HashMap to map purposeName to model index + purposeModelIndexMap = new HashMap(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + int maxUecIndex = 0; + for ( String purposeName : tourPurposeList ) { + int uecIndex = modelStructure.getTourModeChoiceUecIndexForPurpose( purposeName ); + String primaryPurposeName = modelStructure.getPrimaryPurposeString( purposeName ); + purposeModelIndexMap.put( primaryPurposeName, uecIndex ); + modelIndexSet.add( uecIndex ); + if ( uecIndex > maxUecIndex ) + maxUecIndex = uecIndex; + } + + mcModel = new ChoiceModelApplication[maxUecIndex+1]; + + // declare dimensions for the array of choice alternative availability by purpose + modeAltNames = new String[maxUecIndex+1][]; + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + Iterator it = modelIndexSet.iterator(); + while ( it.hasNext() ) { + int m = it.next(); + mcModel[m] = new ChoiceModelApplication ( mcUecFile, m, MC_DATA_SHEET, propertyMap, (VariableTable)mcDmuObject ); + modeAltNames[m] = mcModel[m].getAlternativeNames(); + +// if (filterCount == null){ +// filterCount = new long[mcModel[m].getFilterCount().length][mcModel[m].getFilterCount()[0].length]; +// expressionCount = new long[mcModel[m].getExpressionCount().length][mcModel[m].getExpressionCount()[0].length]; +// coeffCount = new long[mcModel[m].getCoeffCount().length][mcModel[m].getCoeffCount()[0].length]; +// } + + +// try{ +// logger.info ( "mcModel[" + m + "] size: " + ObjectUtil.checkObjectSize(mcModel[m]) ); +// }catch(Exception e){ +// throw(new RuntimeException(e)); +// } + } + + } + + + + /** + * Calculate and return the tour mode choice logsum for the DMU object. + * @param mcDmuObject is the tour mode choice model DMU object + * @return logsum of the tour mode choice alternatives + */ + public double getModeChoiceLogsum ( TourModeChoiceDMU mcDmuObject, String primaryPurposeName, Logger modelLogger, String choiceModelDescription, String decisionMakerLabel ) { + + long check1 = System.nanoTime(); + + int modelIndex = purposeModelIndexMap.get( primaryPurposeName.toLowerCase() ); + + HouseholdIf household = mcDmuObject.getHouseholdObject(); + + + // log headers to traceLogger + if ( household.getDebugChoiceModels() ) { + mcModel[modelIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + } + + + mcModel[modelIndex].computeUtilities( mcDmuObject, mcDmuObject.getDmuIndexValues() ); + double logsum = mcModel[modelIndex].getLogsum(); + + + // write UEC calculation results to separate model specific log file + if( household.getDebugChoiceModels() ){ + if (modelLogger.isDebugEnabled()) { + String loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + mcModel[modelIndex].logUECResults( modelLogger, loggingHeader ); + } + modelLogger.info( choiceModelDescription + " Logsum value: " + logsum ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + + mcLsTotalTime = System.nanoTime() - check1; + + return logsum; + + } + + /** + * Get the choice model application object + */ + public ChoiceModelApplication getChoiceModelApplication ( String primaryPurposeName) { + + int modelIndex = purposeModelIndexMap.get( primaryPurposeName.toLowerCase() ); + return mcModel[modelIndex]; + } + + + + public int getModeChoice ( TourModeChoiceDMU mcDmuObject, String primaryPurposeName ) { + + int modelIndex = purposeModelIndexMap.get( primaryPurposeName ); + + HouseholdIf household = mcDmuObject.getHouseholdObject(); + + Logger modelLogger = null; + if ( tourCategory.equalsIgnoreCase( ModelStructure.MANDATORY_CATEGORY ) ) + modelLogger = tourMCManLogger; + else + modelLogger = tourMCNonManLogger; + + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + String loggingHeader = ""; + String separator = ""; + + + TourIf tour = mcDmuObject.getTourObject(); + + if ( household.getDebugChoiceModels() ) { + + PersonIf person; + if (tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) { + person = tour.getPersonObject(); + } else { + person = mcDmuObject.getPersonObject(); + } + + choiceModelDescription = String.format ( "%s Tour Mode Choice Model for: primaryPurpose=%s, Orig=%d, OrigSubZ=%d, Dest=%d, DestSubZ=%d", tourCategory, primaryPurposeName, household.getHhTaz(), household.getHhWalkSubzone(), tour.getTourDestTaz(), tour.getTourDestWalkSubzone() ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourId=%d", person.getHouseholdObject().getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId() ); + loggingHeader = String.format( "%s %s", choiceModelDescription, decisionMakerLabel ); + + household.logHouseholdObject( "Pre " + tourCategory + " Tour Mode Choice Model HHID=" + household.getHhId(), tourMCManLogger ); + household.logPersonObject( decisionMakerLabel, tourMCManLogger, person ); + + mcModel[modelIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + + modelLogger.info(" "); + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + + household.logTourObject( loggingHeader, modelLogger, person, tour ); + + } + + mcModel[modelIndex].computeUtilities( mcDmuObject, mcDmuObject.getDmuIndexValues() ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen; + if ( mcModel[modelIndex].getAvailabilityCount() > 0 ) + chosen = mcModel[modelIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught for HHID=%d, no available %s tour mode alternatives to choose from in choiceModelApplication.", household.getHhId(), tourCategory ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = mcModel[modelIndex].getUtilities(); // 0s-indexing + double[] probabilities = mcModel[modelIndex].getProbabilities(); // 0s-indexing + boolean[] availabilities = mcModel[modelIndex].getAvailabilities(); // 1s-indexing + String[] altNames = mcModel[modelIndex].getAlternativeNames(); // 0s-indexing + + PersonIf person; + if (tour.getTourCategory().equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) { + person = tour.getPersonObject(); + } else { + person = mcDmuObject.getPersonObject(); + } + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + ", Tour Id: " + tour.getTourId() ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("-------------------- -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < mcModel[modelIndex].getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %s", k+1, altNames[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d %s", chosen, altNames[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to log file + mcModel[modelIndex].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + mcModel[modelIndex].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + mcModel[modelIndex].logLogitCalculations ( choiceModelDescription, decisionMakerLabel ); + + + // write UEC calculation results to separate model specific log file + mcModel[modelIndex].logUECResults( modelLogger, loggingHeader ); + } + + + + if ( saveUtilsProbsFlag ) { + + // get the utilities and probabilities arrays for the tour mode choice model for this tour and save them to the tour object + double[] dUtils = mcModel[modelIndex].getUtilities(); + double[] dProbs = mcModel[modelIndex].getProbabilities(); + + float[] utils = new float[dUtils.length]; + float[] probs = new float[dUtils.length]; + for ( int k=0; k < dUtils.length; k++ ) { + utils[k] = (float)dUtils[k]; + probs[k] = (float)dProbs[k]; + } + + tour.setTourModalUtilities(utils); + tour.setTourModalProbabilities(probs); + + } + + + return chosen; + + } + + public void applyModel( HouseholdIf household ){ + + try { + if (tourCategory.equalsIgnoreCase(ModelStructure.JOINT_NON_MANDATORY_CATEGORY)) { + TourIf[] jointTours = household.getJointTourArray(); + if (jointTours!=null) { + for ( int i=0; i < jointTours.length; i++ ) { + TourIf tour = jointTours[i]; + applyJointModel(household, tour); + } + } + } + } catch ( Exception e ) { + logger.error( String.format( "error in joint tour mode choice model model for hhId=%d.", household.getHhId())); + throw new RuntimeException(e); + } + // get the array of persons for this household + PersonIf[] personArray = household.getPersons(); + + // loop through the persons (1-based array) + for(int j=1;j workTours = person.getListOfWorkTours(); + for ( int i=0; i < workTours.size(); i++ ) { + tour = workTours.get(i); + applyIndividualModel(household, person, tour); + } + ArrayList schoolTours = person.getListOfSchoolTours(); + for (int i=0; i < schoolTours.size(); i++) { + tour = schoolTours.get(i); + applyIndividualModel(household, person, tour); + } + } + else if (tourCategory.equalsIgnoreCase(ModelStructure.INDIVIDUAL_NON_MANDATORY_CATEGORY)) { + ArrayList tours = person.getListOfIndividualNonMandatoryTours(); + for ( int i=0; i < tours.size(); i++ ) { + tour = tours.get(i); + applyIndividualModel(household, person, tour); + } + } + else if (tourCategory.equalsIgnoreCase(ModelStructure.AT_WORK_CATEGORY)) { + ArrayList tours = person.getListOfAtWorkSubtours(); + for ( int i=0; i < tours.size(); i++ ) { + tour = tours.get(i); + applyIndividualModel(household, person, tour); + } + } + } + catch ( Exception e ) { + logger.error( String.format( "error in individual tour mode choice model model for hhId=%d, persId=%d, persNum=%d, personType=%s.", household.getHhId(), person.getPersonId(), person.getPersonNum(), person.getPersonType() )); + logger.error( String.format( "tour id=%d, tour orig=%d, tour dest=%d, tour purpose=%s, tour purpose index=%d.", tour.getTourId(), tour.getTourOrigTaz(), tour.getTourDestTaz(), tour.getTourPrimaryPurpose(), tour.getTourPrimaryPurposeIndex() )); + throw new RuntimeException(e); + } + } + + } + + + private void applyJointModel(HouseholdIf household, TourIf tour) { + PersonIf person = tour.getPersonObject(); + applyIndividualModel(household, person, tour); + } + + private void applyIndividualModel(HouseholdIf household, PersonIf person, TourIf tour) { + + // update the MC dmuObjects for this person + mcDmuObject.setHouseholdObject(household); + mcDmuObject.setPersonObject( person ); + mcDmuObject.setTourObject( tour ); + mcDmuObject.setDmuIndexValues( household.getHhId(), household.getHhTaz(), tour.getTourOrigTaz(), tour.getTourDestTaz(), household.getDebugChoiceModels() ); + mcDmuObject.setTourDepartPeriod( tour.getTourDepartPeriod() ); + mcDmuObject.setTourArrivePeriod( tour.getTourArrivePeriod() ); + + if (tourCategory.equalsIgnoreCase(ModelStructure.AT_WORK_CATEGORY)) { + ArrayList workTourList = person.getListOfWorkTours(); + int workTourIndex = tour.getWorkTourIndexFromSubtourId( tour.getTourId() ); + TourIf workTour = workTourList.get( workTourIndex ); + mcDmuObject.setWorkTourObject(workTour); + } + + //create TVPB for tour mode choice model + setTVPBValues(mcDmuObject, tour.getTourPrimaryPurpose()); + + // use the mcModel object already setup for computing logsums and get the mode choice, where the selected + // worklocation and subzone an departure time and duration are set for this work tour. + int chosenMode = getModeChoice ( mcDmuObject, tour.getTourPrimaryPurpose() ); + tour.setTourModeChoice( chosenMode ); + + //set tour taps + setTourTaps(tour, mcDmuObject, chosenMode); + + if ( household.getDebugChoiceModels() ) { + Logger modelLogger = null; + if ( tourCategory.equalsIgnoreCase( ModelStructure.MANDATORY_CATEGORY ) ) + modelLogger = tourMCManLogger; + else + modelLogger = tourMCNonManLogger; + + modelLogger.info("Chosen mode = " + chosenMode); + String decisionMakerLabel = String.format ( "Final Mode Choice Person Object: HH=%d, PersonNum=%d, PersonType=%s", household.getHhId(), person.getPersonNum(), person.getPersonType() ); + household.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + } + + public String[] getModeAltNames( int purposeIndex ) { + int modelIndex = purposeModelIndexMap.get( tourPurposeList[purposeIndex] ); + return modeAltNames[modelIndex]; + } + +// public long[][] getFilterCount() { +// return filterCount; +// } +// public long[][] getExpressionCount() { +// return expressionCount; +// } +// public long[][] getCoeffCount() { +// return coeffCount; +// } + public long getCmUecTime() { + return cmUecTime; + } + public long getCmOtherTime() { + return cmOtherTime; + } + public long getLsTotalTime() { + return mcLsTotalTime; + } + + public void setTVPBValues(TourModeChoiceDMU mcDmuObject, String purpose) { + + int NA_VALUE = 0; + + //inbound + Trip trip = new Trip(); + trip.setTripid(mcDmuObject.getTourObject().getHhId()); + trip.setOtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getDestZone())); + trip.setDtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getOriginZone())); + trip.setOmaz(mcDmuObject.getDmuIndexValues().getDestZone()); + trip.setDmaz(mcDmuObject.getDmuIndexValues().getOriginZone()); + trip.setAge(mcDmuObject.getTourObject().getPersonObject().getAge()); + trip.setCars(mcDmuObject.getAutos()); + trip.setTod(mcDmuObject.getTodIn()); + trip.setHhincome(mcDmuObject.getHouseholdObject().getIncomeInDollars()); + trip.setInbound(1); + trip.setDebugRecord(mcDmuObject.getHouseholdObject().getDebugChoiceModels()); + + trip.setWalkTimeWeight(mcDmuObject.getTourObject().getPersonObject().getWalkTimeWeight()); + trip.setWalkSpeed(mcDmuObject.getTourObject().getPersonObject().getWalkSpeed()); + trip.setMaxWalk(mcDmuObject.getTourObject().getPersonObject().getMaxWalk()); + trip.setValueOfTime(mcDmuObject.getTourObject().getPersonObject().getValueOfTime()); + + trip.setPurpose(purpose.toLowerCase().startsWith("work") ? 1 : 0); + trip.setUserClassByType("user_class_work_walk", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_walk")); + trip.setUserClassByType("user_class_work_pnr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_pnr")); + trip.setUserClassByType("user_class_work_knr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_work_knr")); + trip.setUserClassByType("user_class_non_work_walk", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_walk")); + trip.setUserClassByType("user_class_non_work_pnr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_pnr")); + trip.setUserClassByType("user_class_non_work_knr", mcDmuObject.getTourObject().getPersonObject().getUserClass("user_class_non_work_knr")); + + tvpb.calculatePathsForATrip(trip, true, true, true); + + TapPair bestWalkTapPair; + TapPair bestKnrTapPair; + TapPair bestPnrTapPair; + if(trip.getWalkTapPairs().size()>0) { + bestWalkTapPair = trip.getWalkTapPairs().get(0); //get best + mcDmuObject.setGenCostWT_In( (float) bestWalkTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapWT_In( bestWalkTapPair.otap ); + mcDmuObject.setDtapWT_In( bestWalkTapPair.dtap ); + } else { + mcDmuObject.setGenCostWT_In( NA_VALUE ); + mcDmuObject.setOtapWT_In( NA_VALUE ); + mcDmuObject.setDtapWT_In( NA_VALUE ); + } + + if(trip.getKnrTapPairs().size()>0) { + bestKnrTapPair = trip.getKnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDL_In( (float) bestKnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDL_In( bestKnrTapPair.otap ); + mcDmuObject.setDtapDL_In( bestKnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDL_In( NA_VALUE ); + mcDmuObject.setOtapDL_In( NA_VALUE ); + mcDmuObject.setDtapDL_In( NA_VALUE ); + } + + if(trip.getPnrTapPairs().size()>0) { + bestPnrTapPair = trip.getPnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDP_In( (float) bestPnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDP_In( bestPnrTapPair.otap ); + mcDmuObject.setDtapDP_In( bestPnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDP_In( NA_VALUE ); + mcDmuObject.setOtapDP_In( NA_VALUE ); + mcDmuObject.setDtapDP_In( NA_VALUE ); + } + + //outbound + trip.setOtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getOriginZone())); + trip.setDtaz(tvpb.getMTTData().getTazForMaz(mcDmuObject.getDmuIndexValues().getDestZone())); + trip.setOmaz(mcDmuObject.getDmuIndexValues().getOriginZone()); + trip.setDmaz(mcDmuObject.getDmuIndexValues().getDestZone()); + trip.setTod(mcDmuObject.getTodOut()); + trip.setInbound(0); + tvpb.calculatePathsForATrip(trip, true, true, true); + + if(trip.getWalkTapPairs().size()>0) { + bestWalkTapPair = trip.getWalkTapPairs().get(0); //get best + mcDmuObject.setGenCostWT_Out( (float) bestWalkTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapWT_Out( bestWalkTapPair.otap ); + mcDmuObject.setDtapWT_Out( bestWalkTapPair.dtap ); + } else { + mcDmuObject.setGenCostWT_Out( NA_VALUE ); + mcDmuObject.setOtapWT_Out( NA_VALUE ); + mcDmuObject.setDtapWT_Out( NA_VALUE ); + } + + if(trip.getKnrTapPairs().size()>0) { + bestKnrTapPair = trip.getKnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDL_Out( (float) bestKnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDL_Out( bestKnrTapPair.otap ); + mcDmuObject.setDtapDL_Out( bestKnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDL_Out( NA_VALUE ); + mcDmuObject.setOtapDL_Out( NA_VALUE ); + mcDmuObject.setDtapDL_Out( NA_VALUE ); + } + + if(trip.getPnrTapPairs().size()>0) { + bestPnrTapPair = trip.getPnrTapPairs().get(0); //get best + mcDmuObject.setGenCostDP_Out( (float) bestPnrTapPair.getTotalUtils()[0] ); + mcDmuObject.setOtapDP_Out( bestPnrTapPair.otap ); + mcDmuObject.setDtapDP_Out( bestPnrTapPair.dtap ); + } else { + mcDmuObject.setGenCostDP_Out( NA_VALUE ); + mcDmuObject.setOtapDP_Out( NA_VALUE ); + mcDmuObject.setDtapDP_Out( NA_VALUE ); + } + + } + + + public void setTourTaps(TourIf tour, TourModeChoiceDMU mcDmuObject, int chosenMode) { + + final int WP_ALT = 10; + final int DL_ALT = 11; + final int DP_ALT = 12; + + //set taps for transit tour mode + if(chosenMode==WP_ALT) { + tour.setTourBTapIn(mcDmuObject.getOtapWT_In()); + tour.setTourATapIn(mcDmuObject.getDtapWT_In()); + tour.setTourBTapOut(mcDmuObject.getOtapWT_Out()); + tour.setTourATapOut(mcDmuObject.getDtapWT_Out()); + } else if (chosenMode==DL_ALT) { + tour.setTourBTapIn(mcDmuObject.getOtapDL_In()); + tour.setTourATapIn(mcDmuObject.getDtapDL_In()); + tour.setTourBTapOut(mcDmuObject.getOtapDL_Out()); + tour.setTourATapOut(mcDmuObject.getDtapDL_Out()); + } else if (chosenMode==DP_ALT) { + tour.setTourBTapIn(mcDmuObject.getOtapDP_In()); + tour.setTourATapIn(mcDmuObject.getDtapDP_In()); + tour.setTourBTapOut(mcDmuObject.getOtapDP_Out()); + tour.setTourATapOut(mcDmuObject.getDtapDP_Out()); + } + } + + +} + diff --git a/src/java/com/pb/models/ctrampIf/jppf/NonMandatoryTourDepartureAndDurationTime.java b/src/java/com/pb/models/ctrampIf/jppf/NonMandatoryTourDepartureAndDurationTime.java new file mode 100644 index 0000000..dc68d53 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/NonMandatoryTourDepartureAndDurationTime.java @@ -0,0 +1,975 @@ +package com.pb.models.ctrampIf.jppf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.*; + +import com.pb.common.calculator.VariableTable; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TourDepartureTimeAndDurationDMU; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.Util; +import com.pb.common.newmodel.ChoiceModelApplication; + +/** + * Created by IntelliJ IDEA. + * User: Jim + * Date: Jul 11, 2008 + * Time: 9:25:30 AM + * To change this template use File | Settings | File Templates. + */ +public class NonMandatoryTourDepartureAndDurationTime implements Serializable { + + + private transient Logger logger = Logger.getLogger( NonMandatoryTourDepartureAndDurationTime.class ); + private transient Logger todLogger = Logger.getLogger( "todLogger" ); + + private static final String INMTOD_UEC_FILE_TARGET = "UecFile.TourDepartureTimeAndDuration"; + private static final String INMTOD_UEC_DATA_TARGET = "departTime.data.page"; + private static final String INMTOD_UEC_ESCORT_MODEL_TARGET = "departTime.escort.page"; + private static final String INMTOD_UEC_SHOP_MODEL_TARGET = "departTime.shop.page"; + private static final String INMTOD_UEC_MAINT_MODEL_TARGET = "departTime.maint.page"; + private static final String INMTOD_UEC_EAT_MODEL_TARGET = "departTime.eat.page"; + private static final String INMTOD_UEC_VISIT_MODEL_TARGET = "departTime.visit.page"; + private static final String INMTOD_UEC_DISCR_MODEL_TARGET = "departTime.discr.page"; + + + private static final String[] tourPurposeNames = { + ModelStructure.ESCORT_PRIMARY_PURPOSE_NAME, + ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME, + ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME, + ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME, + ModelStructure.VISITING_PRIMARY_PURPOSE_NAME, + ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME + }; + + private static final String[] dcModelSheetKeys = { + INMTOD_UEC_ESCORT_MODEL_TARGET, + INMTOD_UEC_SHOP_MODEL_TARGET, + INMTOD_UEC_MAINT_MODEL_TARGET, + INMTOD_UEC_EAT_MODEL_TARGET, + INMTOD_UEC_VISIT_MODEL_TARGET, + INMTOD_UEC_DISCR_MODEL_TARGET + }; + + + // process non-mandatory tours in order by priority purpose: + // 4=escort, 6=oth maint, 5=shop, 8=visiting, 9=oth discr, 7=eat out, + private static final int[] tourPurposeIndexOrder = { + 4, + 6, + 5, + 8, + 9, + 7 + }; + + private ArrayList[] purposeTourLists; + + private int[] todModelIndices; + private HashMap purposeNameIndexMap; + + + + private int[] tourDepartureTimeChoiceSample; + + + // DMU for the UEC + private TourDepartureTimeAndDurationDMU todDmuObject; + private TourModeChoiceDMU mcDmuObject; + + // model structure to compare the .properties time of day with the UECs + private ModelStructure modelStructure; + private String tourCategory; + + private ChoiceModelApplication[] todModels; + private ModeChoiceModel mcModel; + + private int[] altStarts; + private int[] altEnds; + + private boolean[] needToComputeLogsum; + private double[] modeChoiceLogsums; + + private int noAltChoice = 1; + + + + + public NonMandatoryTourDepartureAndDurationTime( HashMap propertyMap, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory, String tourCategory, ModeChoiceModel mcModel ){ + + // set the model structure + this.modelStructure = modelStructure; + this.mcModel = mcModel; + this.tourCategory = tourCategory; + + setUpModels( propertyMap, dmuFactory ); + } + + + public void setUpModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( String.format( "setting up %s time-of-day choice model.", tourCategory ) ); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + String todUecFileName = propertyMap.get( INMTOD_UEC_FILE_TARGET ); + todUecFileName = projectDirectory + todUecFileName; + + todDmuObject = dmuFactory.getTourDepartureTimeAndDurationDMU(); + mcDmuObject = dmuFactory.getModeChoiceDMU(); + + int numLogsumIndices = modelStructure.getPeriodCombinationIndices().length; + needToComputeLogsum = new boolean[numLogsumIndices]; + modeChoiceLogsums = new double[numLogsumIndices]; + + + // create the array of tod model indices + int[] uecSheetIndices = new int[tourPurposeNames.length]; + + purposeNameIndexMap = new HashMap(tourPurposeNames.length); + + int i = 0; + for ( String purposeName : tourPurposeNames ) { + int uecIndex = Util.getIntegerValueFromPropertyMap( propertyMap, dcModelSheetKeys[i]); + purposeNameIndexMap.put(purposeName.toLowerCase(), i); + uecSheetIndices[i] = uecIndex; + i++; + } + + // create a lookup array to map purpose index to model index + todModelIndices = new int[uecSheetIndices.length]; + + // get a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + // also create a HashMap to relate size segment index to SOA Model objects + HashMap modelIndexMap = new HashMap(); + int todModelIndex = 0; + for ( int uecIndex : uecSheetIndices ) { + // if the uec sheet for the model segment is not in the map, add it, otherwise, get it from the map + if ( ! modelIndexMap.containsKey(uecIndex) ) { + modelIndexMap.put( uecIndex, todModelIndex ); + todModelIndices[todModelIndex] = todModelIndex++; + } + else { + todModelIndices[todModelIndex++] = modelIndexMap.get( uecIndex ); + } + } + + + todModels = new ChoiceModelApplication[modelIndexMap.size()]; + int todModelDataSheet = Util.getIntegerValueFromPropertyMap( propertyMap, INMTOD_UEC_DATA_TARGET ); + + for (int uecIndex : modelIndexMap.keySet() ) + { + int modelIndex = modelIndexMap.get(uecIndex); + try + { + todModels[modelIndex] = new ChoiceModelApplication( todUecFileName, uecIndex, todModelDataSheet, propertyMap, (VariableTable) todDmuObject); + } catch (RuntimeException e) + { + logger.error( String.format("exception caught setting up NonMandatory TOD ChoiceModelApplication[%d] for modelIndex=%d, num choice models=%d", modelIndex, modelIndex, modelIndexMap.size()) ); + logger.fatal("Exception caught:", e); + logger.fatal("Throwing new RuntimeException() to terminate."); + throw new RuntimeException(); + } + + } + + + // get the alternatives table from the work tod UEC. + TableDataSet altsTable = todModels[0].getUEC().getAlternativeData(); + + altStarts = altsTable.getColumnAsInt( CtrampApplication.START_FIELD_NAME ); + altEnds = altsTable.getColumnAsInt( CtrampApplication.END_FIELD_NAME ); + todDmuObject.setTodAlts(altStarts, altEnds); + + int numDepartureTimeChoiceAlternatives = todModels[0].getNumberOfAlternatives(); + tourDepartureTimeChoiceSample = new int[numDepartureTimeChoiceAlternatives+1]; + Arrays.fill ( tourDepartureTimeChoiceSample, 1 ); + + // allocate an array of ArrayList objects to hold tour lists by purpose - tour lists will be processed + // in priority purpose order. + int maxPurposeIndex = 0; + for ( i=0; i < tourPurposeIndexOrder.length; i++ ) + if ( tourPurposeIndexOrder[i] > maxPurposeIndex ) + maxPurposeIndex = tourPurposeIndexOrder[i]; + + purposeTourLists = new ArrayList[maxPurposeIndex+1]; + for ( i=0; i < tourPurposeIndexOrder.length; i++ ) { + int index = tourPurposeIndexOrder[i]; + purposeTourLists[index] = new ArrayList(); + } + + } + + + public void applyIndivModel( HouseholdIf hh, boolean runModeChoice ){ + + Logger modelLogger = todLogger; + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + todDmuObject.setHousehold( hh ); + + + + + // get the person objects for this household + PersonIf[] persons = hh.getPersons(); + for ( int p=1; p < persons.length; p++ ) { + + PersonIf person = persons[p]; + + // if no individual non-mandatory tours, nothing to do. + if ( person.getListOfIndividualNonMandatoryTours().size() == 0 ) + continue; + + // arrange the individual non-mandatory tours for this person in an array of ArrayLists by purpose + getPriorityOrderedTourList( person.getListOfIndividualNonMandatoryTours() ); + + + // process tour lists by priority purpose + + // define variables to hold depart/arrive periods selected for the most recent tour. + // if a tour has no non-overlapping period available, set the periods to either the depart or arrive of the most recently determined + // if none has been selected yet, set to the first of last interval + int previouslySelectedDepartPeriod = -1; + int previouslySelectedArrivePeriod = -1; + + for ( int i=0; i < tourPurposeIndexOrder.length; i++ ) { + + int tourPurposeIndex = tourPurposeIndexOrder[i]; + + // process each individual non-mandatory tour from the list + int m = -1; + int tourPurpNum = 1; + int noWindowCountFirstTemp = 0; + int noWindowCountLastTemp = 0; + int noLaterAlternativeCountTemp = 0; + for ( TourIf t : purposeTourLists[tourPurposeIndex] ) { + + try { + + // get the choice model for the tour purpose + String tourPurposeName = t.getTourPrimaryPurpose(); + m = todModelIndices[purposeNameIndexMap.get(tourPurposeName)]; + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( hh.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Individual Non-Mandatory Tour Departure Time Choice Model for: Purpose=%s", tourPurposeName ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d, num=%d of %d %s tours", hh.getHhId(), person.getPersonNum(), person.getPersonType(), t.getTourId(), tourPurpNum, purposeTourLists[tourPurposeIndex].size(), tourPurposeName ); + + todModels[m].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + String loggerString = "Individual Non-Mandatory Tour Departure Time Choice Model: Debug Statement for Household ID: " + hh.getHhId() + ", Person Num: " + person.getPersonNum() + ", Person Type: " + person.getPersonType() + ", Tour Id: " + t.getTourId() + ", num " + tourPurpNum + " of " + purposeTourLists[tourPurposeIndex].size() + " " + tourPurposeName + " tours."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + } + + // set the dmu object + todDmuObject.setHousehold( hh ); + todDmuObject.setPerson( person ); + todDmuObject.setTour( t ); + + + // check for multiple tours for this person, by purpose + // set the first or second switch if multiple tours for person, by purpose + if ( purposeTourLists[tourPurposeIndex].size() == 1 ) { + // not a multiple tour pattern + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( 1 ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else if ( purposeTourLists[tourPurposeIndex].size() > 1 ) { + // Two-plus tour multiple tour pattern + if ( tourPurpNum == 1 ) { + // first of 2+ tours + todDmuObject.setFirstTour( 1 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( tourPurpNum ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else { + // 2nd or greater tours + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 1 ); + todDmuObject.setTourNumber( tourPurpNum ); + // the ArrayList is 0-based, and we want the previous tour, so subtract 2 from tourPurpNum to get the right index + int otherTourEndHour = purposeTourLists[tourPurposeIndex].get( tourPurpNum-2 ).getTourArrivePeriod(); + todDmuObject.setEndOfPreviousScheduledTour( otherTourEndHour ); + } + } + + + + // set the choice availability and sample + boolean[] departureTimeChoiceAvailability = person.getAvailableTimeWindows( altStarts, altEnds ); + Arrays.fill(tourDepartureTimeChoiceSample, 1); + + + if ( departureTimeChoiceAvailability.length != tourDepartureTimeChoiceSample.length ) { + logger.error( String.format( "error in individual non-mandatory departure time choice model for hhId=%d, personNum=%d, tour purpose index=%d, tour ArrayList index=%d.", hh.getHhId(), person.getPersonNum(), tourPurposeIndex, tourPurpNum-1 )); + logger.error( String.format( "length of the availability array determined by the number of alternatives set in the person scheduler=%d", departureTimeChoiceAvailability.length )); + logger.error( String.format( "does not equal the length of the sample array determined by the number of alternatives in the individual non-mandatory tour UEC=%d.", tourDepartureTimeChoiceSample.length )); + throw new RuntimeException(); + } + + + // if all time windows for this person have already been scheduled, choose either the first and last + // alternatives and keep track of the number of times this condition occurs. + int alternativeAvailable = -1; + for (int a=0; a < departureTimeChoiceAvailability.length; a++) { + if ( departureTimeChoiceAvailability[a] ) { + alternativeAvailable = a; + break; + } + } + + int chosen = -1; + int chosenStartPeriod = -1; + int chosenEndPeriod = -1; + + + // alternate making the first and last periods chosen if no alternatives are available + if ( alternativeAvailable < 0 ) { + + if ( noAltChoice == 1 ) { + if ( previouslySelectedDepartPeriod < 0 ) { + chosenStartPeriod = altStarts[noAltChoice-1]; + chosenEndPeriod = altEnds[noAltChoice-1]; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, and no non-mandatory tour scheduled yet, depart AND arrive set to first period=" + chosenStartPeriod + ", " + chosenEndPeriod + "." ); + } + else { + chosenStartPeriod = previouslySelectedArrivePeriod; + chosenEndPeriod = previouslySelectedArrivePeriod; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, depart AND arrive set to arrive period of most recent scheduled non-mandatory tour=" + chosenStartPeriod + ", " + chosenEndPeriod + "." ); + } + noWindowCountFirstTemp++; + noAltChoice = departureTimeChoiceAvailability.length-1; + } + else { + if ( previouslySelectedDepartPeriod < 0 ) { + chosenStartPeriod = altStarts[noAltChoice-1]; + chosenEndPeriod = altEnds[noAltChoice-1]; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, and no non-mandatory tour scheduled yet, depart AND arrive set to last period=" + chosenStartPeriod + ", " + chosenEndPeriod + "." ); + } + else { + chosenStartPeriod = previouslySelectedArrivePeriod; + chosenEndPeriod = previouslySelectedArrivePeriod; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, depart AND arrive set to arrive period of most recent scheduled non-mandatory tour=" + chosenStartPeriod + ", " + chosenEndPeriod + "." ); + } + noWindowCountLastTemp++; + noAltChoice = 1; + if( hh.getDebugChoiceModels() ) + modelLogger.info( "All alternatives already scheduled, depart AND arrive set to work tour arrive period=" + chosenEndPeriod + "." ); + } + + // schedule the chosen alternative + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + previouslySelectedDepartPeriod = chosenStartPeriod; + previouslySelectedArrivePeriod = chosenEndPeriod; + + + if ( runModeChoice ) { + + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre Non-Mandatory Tour Mode Choice Household " + hh.getHhId() + ", Tour " + tourPurpNum + " of " + person.getListOfIndividualNonMandatoryTours().size(), modelLogger ); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(hh, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + else { + + // calculate and store the mode choice logsum for the usual work location for this worker at the various + // departure time and duration alternativees + setTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( t, departureTimeChoiceAvailability ); + + + if( hh.getDebugChoiceModels() ){ + hh.logTourObject( loggingHeader, modelLogger, person, t ); + } + + todDmuObject.setOriginZone( t.getTourOrigTaz() ); + todDmuObject.setDestinationZone(t.getTourDestTaz() ); + + todModels[m].computeUtilities ( todDmuObject, todDmuObject.getIndexValues(), departureTimeChoiceAvailability, tourDepartureTimeChoiceSample ); + + Random hhRandom = hh.getHhRandom(); + int randomCount = hh.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + if ( todModels[m].getAvailabilityCount() > 0 ) + { + chosen = todModels[m].getChoiceResult( rn ); + + // debug output + if( hh.getDebugChoiceModels() ){ + + double[] utilities = todModels[m].getUtilities(); + double[] probabilities = todModels[m].getProbabilities(); + boolean[] availabilities = todModels[m].getAvailabilities(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString + ", Tour Id: " + t.getTourId() + ", Tour num: " + tourPurpNum + " of " + purposeTourLists[tourPurposeIndex].size() + " " + tourPurposeName + " tours." ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < todModels[m].getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d out=%-3d, in=%-3d", k+1, altStarts[k], altEnds[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d out=%-3d, in=%-3d", chosen, altStarts[chosen-1], altEnds[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + todModels[m].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + todModels[m].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s for %s", choiceModelDescription, decisionMakerLabel ); + todModels[m].logUECResults( modelLogger, loggingHeader ); + + } + + } + else { + + // since there were no alternatives with valid utility, assuming previous + // tour of this type scheduled up to the last period, so no periods left + // for this tour. + + //TODO: do a formal check for this so we can still flag other reasons why there's + // no valid utility for any alternative + chosen = departureTimeChoiceAvailability.length-1; + noLaterAlternativeCountTemp++; + + } + + // schedule the chosen alternative + chosenStartPeriod = altStarts[chosen-1]; + chosenEndPeriod = altEnds[chosen-1]; + person.scheduleWindow(chosenStartPeriod, chosenEndPeriod); + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + previouslySelectedDepartPeriod = chosenStartPeriod; + previouslySelectedArrivePeriod = chosenEndPeriod; + + + + if ( runModeChoice ) { + + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre Individual Non-Mandatory Tour Mode Choice Household " + hh.getHhId() + ", Tour " + tourPurpNum + " of " + purposeTourLists[tourPurposeIndex].size(), todLogger ); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(hh, person, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + + } + catch ( Exception e ) { + String errorMessage = String.format( "Exception caught for HHID=%d, personNum=%d, individual non-mandatory Departure time choice, tour ArrayList index=%d.", hh.getHhId(), person.getPersonNum(), tourPurpNum-1 ); + String decisionMakerLabel = String.format ( "Final Individual Non-Mandatory Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", hh.getHhId(), person.getPersonNum(), person.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, person ); + todModels[m].logUECResults( modelLogger, errorMessage ); + + logger.error ( errorMessage, e ); + throw new RuntimeException(); + } + + tourPurpNum++; + + } + + if ( hh.getDebugChoiceModels() ) { + String decisionMakerLabel = String.format ( "Final Individual Non-Mandatory Departure Time Person Object: HH=%d, PersonNum=%d, PersonType=%s", hh.getHhId(), person.getPersonNum(), person.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, person ); + } + + } + + } + + hh.setInmtodRandomCount( hh.getHhRandomCount() ); + + } + + + public void applyJointModel( HouseholdIf hh, boolean runModeChoice ){ + + // if no joint non-mandatory tours, nothing to do for this household. + TourIf[] jointTours = hh.getJointTourArray(); + if ( jointTours == null || jointTours.length == 0 ) + return; + + Logger modelLogger = todLogger; + + // arrange the joint non-mandatory tours for this househol in an array of ArrayLists by purpose + getPriorityOrderedTourList( jointTours ); + + + // process tour lists by priority purpose + for ( int i=0; i < tourPurposeIndexOrder.length; i++ ) { + + int tourPurposeIndex = tourPurposeIndexOrder[i]; + + // process each individual non-mandatory tour from the list + int m = -1; + int tourPurpNum = 1; + int noWindowCountFirstTemp = 0; + int noWindowCountLastTemp = 0; + int noLaterAlternativeCountTemp = 0; + for ( TourIf t : purposeTourLists[tourPurposeIndex] ) { + + try { + + // get the choice model for the tour purpose + String tourPurposeName = t.getTourPrimaryPurpose(); + m = todModelIndices[purposeNameIndexMap.get(tourPurposeName)]; + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( hh.getDebugChoiceModels() ) { + + String personNumsInJointTour = "Person Nums: ["; + for (int n : t.getPersonNumArray()) + personNumsInJointTour += " " + n; + personNumsInJointTour += " ]"; + + choiceModelDescription = String.format ( "Joint Non-Mandatory Tour Departure Time Choice Model for: Purpose=%s", tourPurposeName ); + decisionMakerLabel = String.format ( "HH=%d, tourId=%d, %s, num=%d of %d %s tours", hh.getHhId(), t.getTourId(), personNumsInJointTour, tourPurpNum, purposeTourLists[tourPurposeIndex].size(), tourPurposeName ); + + todModels[m].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + } + + // set the dmu object + todDmuObject.setHousehold( hh ); + todDmuObject.setTour( t ); + + + // check for multiple tours for this person, by purpose + // set the first or second switch if multiple tours for person, by purpose + if ( purposeTourLists[tourPurposeIndex].size() == 1 ) { + // not a multiple tour pattern + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( 1 ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else if ( purposeTourLists[tourPurposeIndex].size() > 1 ) { + // Two-plus tour multiple tour pattern + if ( tourPurpNum == 1 ) { + // first of 2+ tours + todDmuObject.setFirstTour( 1 ); + todDmuObject.setSubsequentTour( 0 ); + todDmuObject.setTourNumber( tourPurpNum ); + todDmuObject.setEndOfPreviousScheduledTour( 0 ); + } + else { + // 2nd or greater tours + todDmuObject.setFirstTour( 0 ); + todDmuObject.setSubsequentTour( 1 ); + todDmuObject.setTourNumber( tourPurpNum ); + // the ArrayList is 0-based, and we want the previous tour, so subtract 2 from tourPurpNum to get the right index + int otherTourEndHour = purposeTourLists[tourPurposeIndex].get( tourPurpNum-2 ).getTourArrivePeriod(); + todDmuObject.setEndOfPreviousScheduledTour( otherTourEndHour ); + } + } + + + + // set the choice availability and sample + boolean[] departureTimeChoiceAvailability = hh.getAvailableJointTourTimeWindows(t, altStarts, altEnds); + Arrays.fill(tourDepartureTimeChoiceSample, 1); + + + if ( departureTimeChoiceAvailability.length != tourDepartureTimeChoiceSample.length ) { + logger.error( String.format( "error in joint non-mandatory departure time choice model for hhId=%d, tour purpose index=%d, tour ArrayList index=%d.", hh.getHhId(), tourPurposeIndex, tourPurpNum-1 )); + logger.error( String.format( "length of the availability array determined by the number of alternatives set in the person schedules=%d", departureTimeChoiceAvailability.length )); + logger.error( String.format( "does not equal the length of the sample array determined by the number of alternatives in the joint non-mandatory tour UEC=%d.", tourDepartureTimeChoiceSample.length )); + throw new RuntimeException(); + } + + + // if all time windows for this person have already been scheduled, choose either the first and last + // alternatives and keep track of the number of times this condition occurs. + int alternativeAvailable = -1; + for (int a=0; a < departureTimeChoiceAvailability.length; a++) { + if ( departureTimeChoiceAvailability[a] ) { + alternativeAvailable = a; + break; + } + } + + int chosen = -1; + int chosenStartPeriod = -1; + int chosenEndPeriod = -1; + + + // alternate making the first and last periods chosen if no alternatives are available + if ( alternativeAvailable < 0 ) { + + if ( noAltChoice == 1 ) { + chosen = 1; + noWindowCountFirstTemp++; + noAltChoice = departureTimeChoiceAvailability.length-1; + } + else { + chosen = departureTimeChoiceAvailability.length-1; + noWindowCountLastTemp++; + noAltChoice = 1; + } + + // schedule the chosen alternative + chosenStartPeriod = altStarts[chosen-1]; + chosenEndPeriod = altEnds[chosen-1]; + hh.scheduleJointTourTimeWindows(t, chosenStartPeriod, chosenEndPeriod); + + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + if( hh.getDebugChoiceModels() ){ + modelLogger.info( "All alternatives already scheduled, chosen set to alt=" + chosen + "." ); + } + + } + else { + + // calculate and store the mode choice logsum for the usual work location for this worker at the various + // departure time and duration alternativees + setTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( t, departureTimeChoiceAvailability ); + + + if( hh.getDebugChoiceModels() ){ + for ( int p=1; p < hh.getPersons().length; p++ ){ + PersonIf pers = hh.getPersons()[p]; + hh.logTourObject( loggingHeader, modelLogger, pers, t ); + } + } + + todDmuObject.setOriginZone( t.getTourOrigTaz() ); + todDmuObject.setDestinationZone(t.getTourDestTaz() ); + + todModels[m].computeUtilities ( todDmuObject, todDmuObject.getIndexValues(), departureTimeChoiceAvailability, tourDepartureTimeChoiceSample ); + + + Random hhRandom = hh.getHhRandom(); + int randomCount = hh.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + if ( todModels[m].getAvailabilityCount() > 0 ) + { + chosen = todModels[m].getChoiceResult( rn ); + + // debug output + if( hh.getDebugChoiceModels() ){ + + double[] utilities = todModels[m].getUtilities(); + double[] probabilities = todModels[m].getProbabilities(); + boolean[] availabilities = todModels[m].getAvailabilities(); + + modelLogger.info("Tour Id: " + t.getTourId() + ", Tour num: " + tourPurpNum + " of " + purposeTourLists[tourPurposeIndex].size() + " " + tourPurposeName + " tours." ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("-------------------- ------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0; k < todModels[m].getNumberOfAlternatives(); k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d out=%-3d, in=%-3d", k+1, altStarts[k], altEnds[k] ); + modelLogger.info( String.format( "%-20s%15s%18.6e%18.6e%18.6e", altString, availabilities[k+1], utilities[k], probabilities[k], cumProb ) ); + } + + modelLogger.info(" "); + String altString = String.format( "%-3d out=%-3d, in=%-3d", chosen, altStarts[chosen-1], altEnds[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info(""); + modelLogger.info(""); + + + // write choice model alternative info to debug log file + todModels[m].logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + todModels[m].logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + // write UEC calculation results to separate model specific log file + loggingHeader = String.format("%s for %s", choiceModelDescription, decisionMakerLabel ); + todModels[m].logUECResults( modelLogger, loggingHeader ); + + } + + } + else { + + // since there were no alternatives with valid utility, assuming previous + // tour of this type scheduled up to the last period, so no periods left + // for this tour. + + //TODO: do a formal check for this so we can still flag other reasons why there's + // no valid utility for any alternative + chosen = departureTimeChoiceAvailability.length-1; + noLaterAlternativeCountTemp++; + + } + + // schedule the chosen alternative + chosenStartPeriod = altStarts[chosen-1]; + chosenEndPeriod = altEnds[chosen-1]; + hh.scheduleJointTourTimeWindows(t, chosenStartPeriod, chosenEndPeriod); + t.setTourDepartPeriod( chosenStartPeriod ); + t.setTourArrivePeriod( chosenEndPeriod ); + + + + + if ( runModeChoice ) { + + if ( hh.getDebugChoiceModels() ) + hh.logHouseholdObject( "Pre Individual Non-Mandatory Tour Mode Choice Household " + hh.getHhId() + ", Tour " + tourPurpNum + " of " + purposeTourLists[tourPurposeIndex].size(), todLogger ); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(hh, null, t, chosenStartPeriod, chosenEndPeriod); + + // use the mcModel object already setup for computing logsums and get + // the mode choice, where the selected + // worklocation and subzone an departure time and duration are set + // for this work tour. + int chosenMode = mcModel.getModeChoice(mcDmuObject, t.getTourPrimaryPurpose()); + t.setTourModeChoice(chosenMode); + + //set tour taps + mcModel.setTourTaps(t, mcDmuObject, chosenMode); + + } + + } + + } + catch ( Exception e ) { + String errorMessage = String.format( "Exception caught for HHID=%d, joint non-mandatory Departure time choice, tour ArrayList index=%d.", hh.getHhId(), tourPurpNum-1 ); + String decisionMakerLabel = "Final Joint Non-Mandatory Departure Time Person Objects:"; + for ( int p=1; p < hh.getPersons().length; p++ ){ + PersonIf pers = hh.getPersons()[p]; + hh.logPersonObject( decisionMakerLabel, modelLogger, pers ); + todModels[m].logUECResults( modelLogger, errorMessage ); + } + + logger.error ( errorMessage, e ); + throw new RuntimeException(); + } + + tourPurpNum++; + + } + + if ( hh.getDebugChoiceModels() ) { + for ( int p=1; p < hh.getPersons().length; p++ ){ + PersonIf pers = hh.getPersons()[p]; + String decisionMakerLabel = String.format ( "Final Joint Non-Mandatory Departure Time Person Objects: HH=%d, PersonNum=%d, PersonType=%s", hh.getHhId(), pers.getPersonNum(), pers.getPersonType() ); + hh.logPersonObject( decisionMakerLabel, modelLogger, pers ); + } + } + + } + + + hh.setJtodRandomCount( hh.getHhRandomCount() ); + + } + + + private void setModeChoiceDmuAttributes(HouseholdIf household, PersonIf person, TourIf t, int startPeriod, int endPeriod) + { + + t.setTourDepartPeriod(startPeriod); + t.setTourArrivePeriod(endPeriod); + + // update the MC dmuObjects for this person + mcDmuObject.setHouseholdObject(household); + mcDmuObject.setPersonObject(person); + mcDmuObject.setTourObject(t); + mcDmuObject.setDmuIndexValues(household.getHhId(), t.getTourOrigTaz(), t.getTourOrigTaz(), t.getTourDestTaz(), household.getDebugChoiceModels()); + + //create TVPB for tour mode choice model + mcModel.setTVPBValues(mcDmuObject, t.getTourPrimaryPurpose()); + + } + + + private void setTourModeChoiceLogsumsForDepartureTimeAndDurationAlternatives( TourIf tour, boolean[] altAvailable ) { + + PersonIf person = tour.getPersonObject(); + HouseholdIf household = person.getHouseholdObject(); + + Arrays.fill(needToComputeLogsum, true); + Arrays.fill(modeChoiceLogsums, -999); + + Logger modelLogger = todLogger; + String choiceModelDescription = String.format( "NonMandatory Tour Mode Choice Logsum calculation for %s Departure Time Choice", tour.getTourPrimaryPurpose()); + String decisionMakerLabel = String.format( "HH=%d, PersonNum=%d, PersonType=%s, tourId=%d of %d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourId(), person.getListOfWorkTours().size()); + String loggingHeader = String.format("%s %s", choiceModelDescription, decisionMakerLabel); + + + for (int a = 1; a <= altStarts.length; a++) + { + + // if the depart/arrive alternative is unavailable, no need to check to see if a logsum has been calculated + if ( ! altAvailable[a] ) + continue; + + int startPeriod = altStarts[a - 1]; + int endPeriod = altEnds[a - 1]; + + int index = modelStructure.getPeriodCombinationIndex(startPeriod, endPeriod); + if (needToComputeLogsum[index]) + { + + String periodString = modelStructure.getPeriodLabel( modelStructure.getPeriodIndex(startPeriod)) + " to " + modelStructure.getPeriodLabel( modelStructure.getPeriodIndex(endPeriod)); + + // set the mode choice attributes needed by @variables in the UEC spreadsheets + setModeChoiceDmuAttributes(household, person, tour, startPeriod, endPeriod); + + if (household.getDebugChoiceModels()) + household.logTourObject(loggingHeader + ", " + periodString, modelLogger, + person, mcDmuObject.getTourObject()); + + try + { + modeChoiceLogsums[index] = mcModel.getModeChoiceLogsum(mcDmuObject, tour.getTourPrimaryPurpose(), + modelLogger, choiceModelDescription, decisionMakerLabel + ", " + periodString); + } catch(Exception e) + { + logger.fatal( "exception caught applying mcModel.getModeChoiceLogsum() for " + periodString + " work tour." ); + logger.fatal( "choiceModelDescription = " + choiceModelDescription ); + logger.fatal( "decisionMakerLabel = " + decisionMakerLabel ); + throw new RuntimeException(e); + } + needToComputeLogsum[index] = false; + } + + } + + todDmuObject.setModeChoiceLogsums(modeChoiceLogsums); + + mcDmuObject.getTourObject().setTourDepartPeriod(0); + mcDmuObject.getTourObject().setTourArrivePeriod(0); + } + + + /** + * takes an ArrayList of individual non-mandatory tours + * creates an array of ArrayLists of tours by purpose + */ + private void getPriorityOrderedTourList( ArrayList toursIn ){ + + // clear the ArrayLists + for ( int i=0; i < purposeTourLists.length; i++ ){ + if ( purposeTourLists[i] != null ) + purposeTourLists[i].clear(); + } + + // go through the list of non-mandatory tours, and put each into an array of ArrayLists, by purpose. + for ( TourIf tour : toursIn ) { + int purposeIndex = tour.getTourPrimaryPurposeIndex(); + purposeTourLists[purposeIndex].add(tour); + } + + } + + /** + * takes an array of joint non-mandatory tours + * creates an array of ArrayLists of tours by purpose + */ + private void getPriorityOrderedTourList( TourIf[] toursIn ){ + + // clear the ArrayLists + for ( int i=0; i < purposeTourLists.length; i++ ){ + if ( purposeTourLists[i] != null ) + purposeTourLists[i].clear(); + } + + // go through the list of non-mandatory tours, and put each into an array of ArrayLists, by purpose. + for ( TourIf tour : toursIn ) { + int purposeIndex = tour.getTourPrimaryPurposeIndex(); + purposeTourLists[purposeIndex].add(tour); + } + + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/SampleOfAlternatives.java b/src/java/com/pb/models/ctrampIf/jppf/SampleOfAlternatives.java new file mode 100644 index 0000000..81167f2 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/SampleOfAlternatives.java @@ -0,0 +1,191 @@ +package com.pb.models.ctrampIf.jppf; + +import com.pb.common.calculator.IndexValues; +import com.pb.models.ctrampIf.SoaDMU; +import com.pb.common.newmodel.ChoiceModelApplication; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Random; + +import org.apache.log4j.Logger; + +/** + * Created on Jul 22, 2003 + * @author Jim Hicks + * + */ +public class SampleOfAlternatives implements java.io.Serializable { + + // the follow arrays are set to the array handles passed in at the time this object is created + private double[] probabilitiesList; + private double[] cumProbabilitiesList; + + + + private ChoiceModelApplication cm; + private int numAlts; + private int numSubzones; + private int sampleSize; + + // these will be dimensioned with the number of unique alternatives (+1) determined for the decision makers + HashMap altFreqMap; + private int[] finalSample; + private float[] sampleCorrectionFactors; + private int numUniqueAlts; + + + + public SampleOfAlternatives ( ChoiceModelApplication cm, int numSubzones, int sampleSize ) { + //public SampleOfAlternatives ( ChoiceModelApplication cm, int numDmuSegments, Object[] objectLocks, double[][] probabilitiesCacheElement, double[][] cumProbabilitiesCacheElement ) { + + this.cm = cm; + numAlts = cm.getUEC().getNumberOfAlternatives(); + this.numSubzones = numSubzones; + this.sampleSize = sampleSize; + + altFreqMap = new HashMap( sampleSize ); + finalSample = new int[sampleSize+1]; + sampleCorrectionFactors = new float[sampleSize+1]; + + } + + + + /* + * apply the sample of alternatives choice model to calculate the sample, sample probabilities, and sample frequencies + */ + public void applySampleOfAlternativesChoiceModel ( String purposeName, SoaDMU soaDmuObject, IndexValues dmuIndex, int origTaz, boolean[] soaAvailability ) { + + Logger soaLogger = Logger.getLogger("slcSoaLogger"); + + altFreqMap.clear(); + + if ( soaDmuObject.getHouseholdObject().getDebugChoiceModels () ) { + String choiceModelDescription = String.format ( "Stop Location SOA Choice Model for: Purpose=%s", purposeName ); + String decisionMakerLabel = String.format ( "HH=%d, origTaz=%d", soaDmuObject.getHouseholdObject().getHhId(), origTaz ); + cm.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + } + + + cm.computeUtilities ( soaDmuObject, dmuIndex ); + probabilitiesList = cm.getProbabilities(); + cumProbabilitiesList = cm.getCumulativeProbabilities(); + + // debug output + if( soaDmuObject.getHouseholdObject().getDebugChoiceModels() ){ + + // write choice model alternative info to debug log file + String choiceModelDescription = String.format("%s Stop Location SOA Choice for origTaz=%d", purposeName, origTaz); + String decisionMakerLabel = String.format(", HHID=%d", soaDmuObject.getHouseholdObject().getHhId() ); + cm.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + + // write UEC calculation results to separate model specific log file + String loggingHeader = choiceModelDescription + decisionMakerLabel; + cm.logUECResults( soaLogger, loggingHeader ); + + } + + + + // loop over sampleSize, select alternatives based on probabilitiesList[dmuSegment], and count frequency of alternatives chosen. + // may include duplicate alternative selections. + int chosenAlt = -1; + + // check to see if the cumulative probability of the next to last alternative is 0. + // if so, then no alternatives were eligable to be in the sample - probably due to the tour mode being walk + // and no stop locations had walk available for both legs. + // if this case hapens, let the stop location be the origin zone. +// if ( cumProbabilitiesList[numAlts - 2] == 0.0 ) { +// +// // set the chosen alternative to the alternative number corresponding to the origin taz, no walk access subzone. +// chosenAlt = origTaz*numSubzones - 2; +// +// // set final sample and corrections accordingly +// finalSample = new int[2]; +// sampleCorrectionFactors = new float[2]; +// +// finalSample[1] = chosenAlt; +// //sampleCorrectionFactors[k+1] = (float)Math.log( (double)freq/prob ); +// sampleCorrectionFactors[1] = (float)Math.log( 1.0 ); +// } +// else { + + Random hhRandom = soaDmuObject.getHouseholdObject().getHhRandom(); + int rnCount = soaDmuObject.getHouseholdObject().getHhRandomCount(); + // when household.getHhRandom() was applied, the random count was incremented, assuming a random number would be drawn right away. + // so let's decrement by 1, then increment the count each time a random number is actually drawn in this method. + rnCount --; + + for (int i=0; i < sampleSize; i++) { + + double rn = hhRandom.nextDouble(); + rnCount++; + chosenAlt = cm.getChoiceIndexFromCumProbabilities( cumProbabilitiesList, rn ); + + // write choice model alternative info to log file + if ( soaDmuObject.getHouseholdObject().getDebugChoiceModels () ) { + cm.logSelectionInfo ( String.format("%s Sample Of Alternatives Choice for dmuSegment=%d", purposeName, origTaz), String.format("HHID=%d, rnCount=%d", soaDmuObject.getHouseholdObject().getHhId(), rnCount), rn, chosenAlt ); + } + + int freq = 0; + if ( altFreqMap.containsKey(chosenAlt) ) + freq = altFreqMap.get( chosenAlt ); + altFreqMap.put(chosenAlt, (freq + 1) ); + + } + + // sampleSize random number draws were made from this Random object, so update the count in the hh's Random. + soaDmuObject.getHouseholdObject().setHhRandomCount( rnCount ); + + + // create arrays of the unique chosen alternatives and the frequency with which those alternatives were chosen. + numUniqueAlts = altFreqMap.size(); + Iterator it = altFreqMap.keySet().iterator(); + int k = 0; + while ( it.hasNext() ) { + + int alt = it.next(); + int freq = altFreqMap.get( alt ); + + double prob = 0; + prob = probabilitiesList[alt-1]; + + finalSample[k+1] = alt; + sampleCorrectionFactors[k+1] = (float)Math.log( (double)freq/prob ); + + k++; + } + +// } + + } + + + + + public int getNumUniqueAlts() { + return numUniqueAlts; + } + + + /* + * return array with sample of alternatives + */ + public int[] getSampleOfAlternatives () { + return finalSample; + } + + + /* + * return array with sample of alternatives correction factors + */ + public float[] getSampleCorrectionFactors () { + return sampleCorrectionFactors; + } + + + public void choiceModelUtilityTraceLoggerHeading( String choiceModelDescription, String decisionMakerLabel ) { + cm.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/StopDepartArrivePeriodModel.java b/src/java/com/pb/models/ctrampIf/jppf/StopDepartArrivePeriodModel.java new file mode 100644 index 0000000..a1e6ae0 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/StopDepartArrivePeriodModel.java @@ -0,0 +1,127 @@ +package com.pb.models.ctrampIf.jppf; + +import com.pb.common.datafile.OLD_CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.ModelStructure; +import java.io.File; +import java.io.Serializable; +import java.util.HashMap; +import org.apache.log4j.Logger; + +/** + * This class will be used for determining the number of stops on individual + * mandatory, individual non-mandatory and joint tours. + * + * @author Christi Willison + * @version Nov 4, 2008 + *

+ * Created by IntelliJ IDEA. + */ +public class StopDepartArrivePeriodModel implements Serializable +{ + + private transient Logger logger = Logger.getLogger(StopDepartArrivePeriodModel.class); + + private static final String PROPERTIES_STOP_TOD_LOOKUP_FILE = "stop.depart.arrive.proportions"; + + // define names used in lookup file + private static final String TOUR_PURPOSE_INDEX_COLUMN_HEADING = "tourpurp"; + private static final String HALF_TOUR_DIRECTION_COLUMN_HEADING = "isInbound"; + private static final String TOUR_TOD_PERIOD_HEADING = "interval"; + private static final String TRIP_NUMBER_COLUMN_HEADING = "trip"; + private static final String INTERVAL_1_PROPORTION_COLUMN_HEADING = "p1"; + + private static final int NUM_DIRECTIONS = 2; + private static final int NUM_TRIPS = 4; + + + private double[][][][][] proportions; + + private ModelStructure modelStructure; + + + /** + * Constructor + * @param propertyMap - properties HashMap + * @param modelStructure - model definitions helper class + */ + public StopDepartArrivePeriodModel(HashMap propertyMap, ModelStructure modelStructure) + { + this.modelStructure = modelStructure; + setupModels(propertyMap); + } + + private void setupModels(HashMap propertyMap) + { + + logger.info(String.format("setting up stop depart/arrive choice model.")); + + String propsFile = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ) + propertyMap.get(PROPERTIES_STOP_TOD_LOOKUP_FILE); + + // read the stop purpose lookup table data and populate the maps used to assign stop purposes + readLookupProportions(propsFile); + + } + + private void readLookupProportions(String propsLookupFilename) + { + + // read the stop purpose proportions into a TableDataSet + TableDataSet propsLookupTable = null; + String fileName = ""; + try { + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + propsLookupTable = reader.readFile(new File(propsLookupFilename)); + } + catch (Exception e) { + logger.error( String.format( "Exception occurred reading stop purpose lookup proportions file: %s.", fileName ), e ); + throw new RuntimeException(); + } + + + // allocate an array for storing proportions arrays. + int lastInterval = modelStructure.getTimePeriodIndexForTime( ModelStructure.LAST_TOD_INTERVAL_HOUR ); + proportions = new double[ModelStructure.NUM_PRIMARY_PURPOSES+1][NUM_DIRECTIONS][lastInterval+1][NUM_TRIPS+1][lastInterval+1]; + + + + // fields in lookup file are: + // tourpurp isInbound interval trip p1-p40 (alternative interval proportions) + + // populate the outProportionsMaps and inProportionsMaps arrays of maps from data in the TableDataSet. + // when stops are generated, they can lookup the proportions for stop depart or arrive interval determined + // by tour purpose, outbound/inbound direction and interval of previous trip. From these proportions, + // a stop tod interval can be drawn. + + // loop over rows in the TableDataSet + for (int i = 0; i < propsLookupTable.getRowCount(); i++) { + + // get the tour primary purpose index (1-10) + int tourPrimaryPurposeIndex = (int) propsLookupTable.getValueAt(i + 1, TOUR_PURPOSE_INDEX_COLUMN_HEADING); + + // get the half tour direction (0 for outbound or 1 for inbound) + int direction = (int) propsLookupTable.getValueAt(i + 1, HALF_TOUR_DIRECTION_COLUMN_HEADING); + + // get the tod interval (1-40) + int todInterval = (int) propsLookupTable.getValueAt(i + 1, TOUR_TOD_PERIOD_HEADING); + + // get the trip number (1-4) + int tripNumber = (int) propsLookupTable.getValueAt(i + 1, TRIP_NUMBER_COLUMN_HEADING); + + // get the index of the first alternative TOD interval proportion. + int firstPropColumn = propsLookupTable.getColumnPosition(INTERVAL_1_PROPORTION_COLUMN_HEADING); + + // starting at this column, read the proportions for all TOD interval proportions. + // Create the array of proportions for this table record. + for (int j = 1; j <= lastInterval; j++) + proportions[tourPrimaryPurposeIndex][direction][todInterval][tripNumber][j] = propsLookupTable.getValueAt(i + 1, firstPropColumn + j-1); + + } + + } + + public double[] getStopTodIntervalProportions( int tourPrimaryPurposeIndex, int direction, int prevTripTodInterval, int tripNumber ) { + return proportions[tourPrimaryPurposeIndex][direction][prevTripTodInterval][tripNumber]; + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/StopDestinationSampleOfAlternativesModel.java b/src/java/com/pb/models/ctrampIf/jppf/StopDestinationSampleOfAlternativesModel.java new file mode 100644 index 0000000..b782a13 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/StopDestinationSampleOfAlternativesModel.java @@ -0,0 +1,308 @@ +package com.pb.models.ctrampIf.jppf; + +import org.apache.log4j.Logger; + +import java.io.Serializable; +import java.util.Map; +import java.util.HashMap; + +import com.pb.common.calculator.VariableTable; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.StopDCSoaDMU; +import com.pb.models.ctrampIf.StopDestChoiceSize; +import com.pb.models.ctrampIf.StopIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; +/** + * @author crf
+ * Started: Nov 14, 2008 3:09:14 PM + */ +public class StopDestinationSampleOfAlternativesModel implements Serializable { + + private transient Logger logger = Logger.getLogger(StopDestinationSampleOfAlternativesModel.class); + + private static final String PROPERTIES_UEC_STOP_LOCATION_SOA = "UecFile.StopLocationSoa"; + private static final String PROPERTIES_STOP_LOCATION_SOA_SAMPLE_SIZE = "StopLocationSoa.SampleSize"; + + private static final int STOP_SOA_DATA_SHEET = 0; + private static final int SOA_WORK_UEC_MODEL_PAGE = 1; + private static final int SOA_UNIVERSITY_UEC_MODEL_PAGE = 2; + private static final int SOA_SCHOOL_UEC_MODEL_PAGE = 3; + private static final int SOA_ESCORT_UEC_MODEL_PAGE = 4; + private static final int SOA_SHOPPING_UEC_MODEL_PAGE = 5; + private static final int SOA_EAT_OUT_UEC_MODEL_PAGE = 6; + private static final int SOA_OTH_MAINT_UEC_MODEL_PAGE = 7; + private static final int SOA_SOCIAL_UEC_MODEL_PAGE = 8; + private static final int SOA_OTH_DISC_UEC_MODEL_PAGE = 9; + private static final int SOA_AT_WORK_UEC_MODEL_PAGE = 10; + + private static final int SOA_WORK_STOP_PURPOSE_INDEX = 1; + private static final int SOA_ESCORT_STOP_PURPOSE_INDEX = 2; + private static final int SOA_SHOPPING_STOP_PURPOSE_INDEX = 3; + private static final int SOA_EAT_OUT_STOP_PURPOSE_INDEX = 4; + private static final int SOA_OTH_MAINT_STOP_PURPOSE_INDEX = 5; + private static final int SOA_SOCIAL_STOP_PURPOSE_INDEX = 6; + private static final int SOA_OTH_DISC_STOP_PURPOSE_INDEX = 7; + + private Map uecPageMap; + private Map lookupIndexMap; + + + private String stopSoaUecFileName; + private StopDCSoaDMU stopSoaDmu; + private int sampleSize; + + private Map soa; + private Map destinationAvailability; + private Map logSizeTerms; + + private ModelStructure modelStructure; + + + public StopDestinationSampleOfAlternativesModel( HashMap propertyMap, TazDataIf tazDataManager, StopDestChoiceSize sizeModel, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + this.modelStructure = modelStructure; + setup( propertyMap, tazDataManager, sizeModel, modelStructure, dmuFactory ); + } + + + //private void setup( HashMap propertyMap, TazDataIf tazDataManager, StopDestChoiceSize sizeModel, HashMap objectLockMap, HashMap probabilitiesMap, HashMap cumProbabilitiesMap ) { + private void setup( HashMap propertyMap, TazDataIf tazDataManager, StopDestChoiceSize sizeModel, ModelStructure modelStructure, CtrampDmuFactoryIf dmuFactory ) { + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + stopSoaUecFileName = projectDirectory + propertyMap.get(PROPERTIES_UEC_STOP_LOCATION_SOA); + sampleSize = Integer.parseInt( propertyMap.get(PROPERTIES_STOP_LOCATION_SOA_SAMPLE_SIZE) ); + stopSoaDmu = dmuFactory.getStopDCSoaDMU(); + + uecPageMap = new HashMap(); + uecPageMap.put(ModelStructure.WORK_PURPOSE_NAME,SOA_WORK_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.UNIVERSITY_PURPOSE_NAME,SOA_UNIVERSITY_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.SCHOOL_PURPOSE_NAME,SOA_SCHOOL_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.ESCORT_PURPOSE_NAME,SOA_ESCORT_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.SHOPPING_PURPOSE_NAME,SOA_SHOPPING_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.EAT_OUT_PURPOSE_NAME,SOA_EAT_OUT_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.OTH_MAINT_PURPOSE_NAME,SOA_OTH_MAINT_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.SOCIAL_PURPOSE_NAME,SOA_SOCIAL_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.OTH_DISCR_PURPOSE_NAME,SOA_OTH_DISC_UEC_MODEL_PAGE); + uecPageMap.put(ModelStructure.AT_WORK_PURPOSE_NAME,SOA_AT_WORK_UEC_MODEL_PAGE); + + lookupIndexMap = new HashMap(); + lookupIndexMap.put(ModelStructure.WORK_PURPOSE_NAME,SOA_WORK_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.UNIVERSITY_PURPOSE_NAME,SOA_WORK_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.SCHOOL_PURPOSE_NAME,SOA_WORK_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.ESCORT_PURPOSE_NAME,SOA_ESCORT_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.SHOPPING_PURPOSE_NAME,SOA_SHOPPING_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.EAT_OUT_PURPOSE_NAME,SOA_EAT_OUT_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.OTH_MAINT_PURPOSE_NAME,SOA_OTH_MAINT_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.SOCIAL_PURPOSE_NAME,SOA_SOCIAL_STOP_PURPOSE_INDEX); + lookupIndexMap.put(ModelStructure.OTH_DISCR_PURPOSE_NAME,SOA_OTH_DISC_STOP_PURPOSE_INDEX); + + int numberOfZones = tazDataManager.getNumberOfZones(); + int numberOfSubZones = tazDataManager.getNumberOfSubZones(); + int numberOfAvailableZones = numberOfZones*tazDataManager.getNumberOfSubZones(); + int[] altToZone = tazDataManager.getAltToZoneArray(); + int[] altToSubZone = tazDataManager.getAltToSubZoneArray(); + + // /purposes save escort\ /escort purposes \ /inbound and outbound tours\ +// int numberOfPurposes = (uecPageMap.size() - 1 + modelStructure.ESCORT_SEGMEMT_NAMES.length) * 2; + + soa = new HashMap(); + destinationAvailability = new HashMap(); + logSizeTerms = new HashMap(); + + + for ( String purpose : uecPageMap.keySet()) { + int uecPage = uecPageMap.get( purpose ); + try { + ChoiceModelApplication choiceModel = new ChoiceModelApplication (stopSoaUecFileName, uecPage, STOP_SOA_DATA_SHEET, propertyMap, (VariableTable)stopSoaDmu ); + soa.put( uecPage, new SampleOfAlternatives( choiceModel, numberOfSubZones, sampleSize ) ); + //soa.put(index,new SampleOfAlternatives( choiceModel, numberOfZones, objLocks, probs, cumProbs)); + } catch (RuntimeException e) { + logger.error (String.format("exception caught setting up STOP SOA UEC model index for tour purpose %s", purpose, e)); + throw e; + } + } + + + + for (String purpose : lookupIndexMap.keySet()) { + if (purpose.equals(ModelStructure.ESCORT_PURPOSE_NAME)) { + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,true,true), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,false,true), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,true,false), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,false,false), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + } else { + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,true), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + setSoaModelInfo( propertyMap, getPurposeLookupIndex(purpose,false), numberOfSubZones, numberOfAvailableZones, sizeModel, altToZone, altToSubZone ); + } + } +// for (String purpose : uecPageMap.keySet()) { +// if (purpose.equals(modelStructure.ESCORT_PURPOSE_NAME)) { +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,true,true),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,false,true),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,true,false),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,false,false),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// } else { +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,true),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// setSoaModelInfo(propertyMap,getPurposeLookupIndex(purpose,false),uecPageMap.get(purpose),numberOfZones,numberOfAvailableZones,sizeModel,altToZone,altToSubZone,objectLockMap.get(purpose),probabilitiesMap.get(purpose),cumProbabilitiesMap.get(purpose)); +// } +// } + + } + + //private void setSoaModelInfo( HashMap propertyMap, int index, int uecPage, int numberOfZones, int numberOfAlternatives, StopDestChoiceSize sizeModel, int[] altToZone, int[] altToSubZone, Object[] objLocks, double[][] probs, double[][] cumProbs ) { + private void setSoaModelInfo( HashMap propertyMap, int index, int numberOfSubZones, int numberOfAlternatives, StopDestChoiceSize sizeModel, int[] altToZone, int[] altToSubZone ) { + + boolean[] destAvailability; + double[] logSizeTerm; + if (destinationAvailability.containsKey(-1*index)) { //use already computed inbound/outbound value, if it exists + destAvailability = destinationAvailability.get(-1*index); + logSizeTerm = logSizeTerms.get(-1*index); + } else { + destAvailability = new boolean[numberOfAlternatives+1]; + logSizeTerm = new double[numberOfAlternatives+1]; + for (int i=1; i <= numberOfAlternatives; i++) { + int zone = altToZone[i]; + int subzone = altToSubZone[i]; + String[] purposeSegments = getMainAndSubPurposeFromLookupIndex(index); + double size = sizeModel.getDcSize(purposeSegments[0].toLowerCase(), purposeSegments[1].toLowerCase(), zone, subzone ); + destAvailability[i] = size > 0.0; + logSizeTerm[i] = size > 0.0 ? Math.log(1+size) : 0.0; + } + } + destinationAvailability.put(index,destAvailability); + logSizeTerms.put(index,logSizeTerm); + } + + private int getPurposeLookupIndex(String purpose, boolean inbound) { + return getPurposeLookupIndex(purpose,inbound,false); + } + + /*lookup index is an integer: [uecPage][has kids], where if kids are present (where it matters) it is 1, else 0 + * the indedx is multiplied by -1 if it is inbound, otherwise it is > 0 */ + private int getPurposeLookupIndex(String purpose, boolean inbound, boolean hasKids) { + return (lookupIndexMap.get(purpose)*10 + (hasKids ? 1 : 0)) * (inbound ? 1 : -1); + } + +// private String getPurposeFromLookupIndex(int lookupIndex) { +// StringBuilder sb = new StringBuilder(); +// if (lookupIndex < 0) { +// sb.append(" outbound"); +// lookupIndex *= -1; +// } else { +// sb.append(" inbound"); +// } +// int purposeIndex = lookupIndex / 10; +// for (String purpose : lookupIndexMap.keySet()) { +// if (lookupIndexMap.get(purpose) == purposeIndex) { +// if (purpose.equals(modelStructure.ESCORT_PURPOSE_NAME)) +// sb.insert(0,(lookupIndex - purposeIndex*10 == 1) ? " kids" : " no kids"); +// sb.insert(0,purpose); +// break; +// } +// } +// return sb.toString(); +// } + + private String[] getMainAndSubPurposeFromLookupIndex(int lookupIndex) { + lookupIndex = Math.abs(lookupIndex); + int purposeIndex = lookupIndex / 10; + String[] purposeSegments = new String[2]; + for (String purpose : lookupIndexMap.keySet()) { + if (lookupIndexMap.get(purpose) == purposeIndex) { + if (purpose.equals(ModelStructure.ESCORT_PURPOSE_NAME) & modelStructure.getNumEscortSegments() > 0) + //0 = kids, 1 = no kids in modelStructure, oposite in lookupIndex + purposeSegments[1] = modelStructure.ESCORT_SEGMENT_NAMES[1 - lookupIndex + purposeIndex*10]; + else + purposeSegments[1] = purpose; + purposeSegments[0] = purpose; + break; + } + } + return purposeSegments; + } + + private final StopSoaResult soaResult= new StopSoaResult(); + + public class StopSoaResult implements Serializable { + private int[] sample; + private float[] corrections; + private double[] stopLocationSize; + private int numUniqueAlts; + private StopSoaResult() {} + private void setSample(int[] sample) { + this.sample = sample; + } + private void setCorrections(float[] corrections) { + this.corrections = corrections; + } + private void setNumUniqueAltsInSample( int numAlts ){ + this.numUniqueAlts = numAlts; + } + private void setStopLocationSize( double[] stopLocSize ){ + this.stopLocationSize = stopLocSize; + } + + public int getNumUniqueAltsInSample() { + return numUniqueAlts; + } + public int[] getSample() { + return sample; + } + public float[] getCorrections() { + return corrections; + } + public double[] getStopLocationSize() { + return stopLocationSize; + } + } + + public StopSoaResult computeDestinationSampleOfAlternatives( StopIf s ) { + boolean inbound = s.isInboundStop(); + String stopPurpose = modelStructure.getPrimaryPurposeForIndex( s.getDestPurposeIndex() ); + int stopOrig = s.getOrig(); + int lookupIndex; + boolean hasKids = false; + TourIf t = s.getTour(); + int tourDest = inbound ? t.getTourOrigTaz() : t.getTourDestTaz(); + String tourPurpose = t.getTourPrimaryPurpose(); + + HouseholdIf hh = t.getPersonObject().getHouseholdObject(); + + if ( stopPurpose.equals(ModelStructure.ESCORT_PURPOSE_NAME) ) { + hasKids = hh.getNumChildrenUnder19() > 0; + lookupIndex = getPurposeLookupIndex( ModelStructure.ESCORT_PURPOSE_NAME, inbound, hasKids ); + } else { + lookupIndex = getPurposeLookupIndex( stopPurpose, inbound ); + } + double[] stopLocSize = logSizeTerms.get(lookupIndex); + stopSoaDmu.setDmuState( hh.getHhTaz(), stopOrig, tourDest, hh, t, inbound, hasKids, stopLocSize ); + + // apply sample of alternatives model for the work segment to which this worker belongs. + int uecPage = uecPageMap.get( tourPurpose ); + SampleOfAlternatives soaModel = soa.get( uecPage ); + + soaModel.applySampleOfAlternativesChoiceModel ( tourPurpose, stopSoaDmu, stopSoaDmu.getDmuIndexValues(), stopOrig, destinationAvailability.get(lookupIndex) ); + + soaResult.setSample( soaModel.getSampleOfAlternatives() ); + soaResult.setCorrections( soaModel.getSampleCorrectionFactors() ); + soaResult.setNumUniqueAltsInSample( soaModel.getNumUniqueAlts() ); + soaResult.setStopLocationSize( stopLocSize ); + return soaResult; + } + + + public void cleanUp() { + soa = null; + } + + + public int getSampleOfAlternativesSampleSize() { + return sampleSize; + } + + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/StopFrequencyModel.java b/src/java/com/pb/models/ctrampIf/jppf/StopFrequencyModel.java new file mode 100644 index 0000000..85164cb --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/StopFrequencyModel.java @@ -0,0 +1,692 @@ +package com.pb.models.ctrampIf.jppf; + +import com.pb.common.calculator.VariableTable; +import com.pb.common.datafile.OLD_CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.StopFrequencyDMU; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.common.newmodel.ChoiceModelApplication; +import java.io.File; +import java.io.Serializable; +import java.util.*; + +import org.apache.log4j.Logger; + +/** + * This class will be used for determining the number of stops + * on individual mandatory, individual non-mandatory and joint + * tours. + * + * @author Christi Willison + * @version Nov 4, 2008 + *

+ * Created by IntelliJ IDEA. + */ +public class StopFrequencyModel implements Serializable { + + private transient Logger logger = Logger.getLogger(StopFrequencyModel.class); + private transient Logger stopFreqLogger = Logger.getLogger("stopFreqLog"); + + private static final String PROPERTIES_UEC_STOP_FREQ = "UecFile.StopFrequency"; + private static final String PROPERTIES_STOP_PURPOSE_LOOKUP_FILE = "StopPurposeLookup.Proportions"; + + + + private static final int UEC_DATA_PAGE = 0; + + // define names used in lookup file + private static final String TOUR_PRIMARY_PURPOSE_COLUMN_HEADING = "PrimPurp"; + private static final String HALF_TOUR_DIRECTION_COLUMN_HEADING = "Direction"; + private static final String TOUR_DEPARTURE_START_RANGE_COLUMN_HEADING = "DepartRangeStart"; + private static final String TOUR_DEPARTURE_END_RANGE_COLUMN_HEADING = "DepartRangeEnd"; + private static final String PERSON_TYPE_COLUMN_HEADING = "Ptype"; + + private static final String OUTBOUND_DIRECTION_NAME = "Outbound"; + private static final String INBOUND_DIRECTION_NAME = "Inbound"; + + private static final String WORK_PURPOSE_NAME_IN_FILE = "Work"; + private static final String UNIVERSITY_PURPOSE_NAME_IN_FILE = "University"; + private static final String SCHOOL_PURPOSE_NAME_IN_FILE = "School"; + private static final String ESCORT_PURPOSE_NAME_IN_FILE = "Escort"; + private static final String SHOP_PURPOSE_NAME_IN_FILE = "Shop"; + private static final String OTH_MAINT_PURPOSE_NAME_IN_FILE = "Maintenance"; + private static final String EAT_OUT_PURPOSE_NAME_IN_FILE = "Eating Out"; + private static final String SOCIAL_PURPOSE_NAME_IN_FILE = "Visiting"; + private static final String OTH_DISCR_PURPOSE_NAME_IN_FILE = "Discretionary"; + private static final String AT_WORK_PURPOSE_NAME_IN_FILE = "Work-Based"; + + + private static final String FT_WORKER_PERSON_TYPE_NAME = "FT Worker"; + private static final String PT_WORKER_PERSON_TYPE_NAME = "PT Worker"; + private static final String UNIVERSITY_PERSON_TYPE_NAME = "University Student"; + private static final String NONWORKER_PERSON_TYPE_NAME = "Homemaker"; + private static final String RETIRED_PERSON_TYPE_NAME = "Retired"; + private static final String DRIVING_STUDENT_PERSON_TYPE_NAME = "Driving-age Child"; + private static final String NONDRIVING_STUDENT_PERSON_TYPE_NAME = "Pre-Driving Child"; + private static final String PRESCHOOL_PERSON_TYPE_NAME = "Preschool"; + private static final String ALL_PERSON_TYPE_NAME = "All"; + + + + private TazDataIf tazDataManager; + private ModelStructure modelStructure; + + private StopFrequencyDMU dmuObject; + private ChoiceModelApplication[] choiceModelApplication; + + private HashMap indexPurposeMap; + private HashMap[] outProportionsMaps; + private HashMap[] inProportionsMaps; + + private int[] zoneTableRow; + private int[] areaType; + + + + + + /** + * Constructor that will be used to set up the ChoiceModelApplications for each + * type of tour + * @param projectDirectory - name of root level project directory + * @param resourceBundle - properties file with paths identified + * @param dmuObject - decision making unit for stop frequency + * @param tazDataManager - holds information about TAZs in the model. + */ + public StopFrequencyModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + this.tazDataManager = tazDataManager; + this.modelStructure = modelStructure; + + setupModels( propertyMap, dmuFactory ); + + } + + + + private void setupModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( String.format( "setting up stop frequency choice models." ) ); + + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + // locate the UEC + String uecFileName = propertyMap.get( PROPERTIES_UEC_STOP_FREQ ); + uecFileName = projectDirectory + uecFileName; + + + dmuObject = dmuFactory.getStopFrequencyDMU(); + + + float[] pkTransitRetail = tazDataManager.getPkTransitRetailAccessibity(); + float[] opTransitRetail = tazDataManager.getOpTransitRetailAccessibity(); + float[] nonMotorizedRetail = tazDataManager.getNonMotorizedRetailAccessibity(); + + dmuObject.setZonalAccessibilities( pkTransitRetail, opTransitRetail, nonMotorizedRetail ); + + + // get the zone table row correspondence array for TAZs + zoneTableRow = tazDataManager.getZoneTableRowArray(); + + // the zone table columns below returned use 0-based indexing + areaType = tazDataManager.getZonalAreaType(); + + + // set up the model array + TreeSet modelSheets = modelStructure.getStopFreqModelSheetIndices(); + choiceModelApplication = new ChoiceModelApplication[modelSheets.size()+1]; // one choice model for each model sheet specified + for ( int i : modelSheets ) { + if ( choiceModelApplication[i] == null ) + choiceModelApplication[i] = new ChoiceModelApplication( uecFileName, i, UEC_DATA_PAGE, propertyMap, (VariableTable)dmuObject ); + } + + + String purposeLookupFileName = projectDirectory + propertyMap.get(PROPERTIES_STOP_PURPOSE_LOOKUP_FILE); + + // read the stop purpose lookup table data and populate the maps used to assign stop purposes + readPurposeLookupProportionsTable( purposeLookupFileName ); + + } + + + + public void applyModel( HouseholdIf household ){ + + int totalStops = 0; + int totalTours = 0; + + Logger modelLogger = stopFreqLogger; + if ( household.getDebugChoiceModels() ) + household.logHouseholdObject( "Pre Stop Frequency Choice: HH=" + household.getHhId(), stopFreqLogger ); + + + // get this household's person array + PersonIf[] personArray = household.getPersons(); + + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmu + dmuObject.setHouseholdObject(household); + + + /* + // process the joint tours for the household first + TourIf[] jt = household.getJointTourArray(); + if ( jt != null ) { + + List tourList = new ArrayList(); + + for ( TourIf t : jt ) + tourList.add( t ); + + int tourCount = 0; + for ( TourIf tour : tourList ) { + + try { + + int modelIndex = modelStructure.getStopFrequencyModelIndex( tour.getTourPrimaryPurpose().toLowerCase() ); + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Joint Tour Stop Frequency Choice Model:" ); + decisionMakerLabel = String.format ( "HH=%d, TourType=%s, TourId=%d, TourPurpose=%s.", household.getHhId(), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourId(), tour.getTourPrimaryPurpose() ); + + choiceModelApplication[modelIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + } + + + + // set the tour object + dmuObject.setTourObject(tour); + + // set the area type for the origin taz + int tableRow = zoneTableRow[tour.getTourOrigTaz()]; + dmuObject.setOriginTazAreaType( areaType[tableRow-1] ); + + // set the area type for the primary destination taz + tableRow = zoneTableRow[tour.getTourDestTaz()]; + dmuObject.setDestTazAreaType( areaType[tableRow-1] ); + + // compute the utilities + dmuObject.setDmuIndexValues( household.getHhId(), household.getHhTaz(), tour.getTourOrigTaz(), tour.getTourDestTaz() ); + + choiceModelApplication[modelIndex].computeUtilities(dmuObject, dmuObject.getDmuIndexValues() ); + + // get the random number from the household + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int choice = -1; + if ( choiceModelApplication[modelIndex].getAvailabilityCount() > 0 ) + choice = choiceModelApplication[modelIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught applying joint tour stop frequency choice model for %s type tour: HHID=%d, tourCount=%d, randomCount=%f -- no avaialable stop frequency alternative to choose.", ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], household.getHhId(), tourCount, randomCount ) ); + throw new RuntimeException(); + } + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = choiceModelApplication[modelIndex].getUtilities(); + double[] probabilities = choiceModelApplication[modelIndex].getProbabilities(); + String[] altNames = choiceModelApplication[modelIndex].getAlternativeNames(); // 0s-indexing + + modelLogger.info( decisionMakerLabel ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0;k tourList = new ArrayList(); + + // apply stop frequency for all person tours + tourList.addAll( person.getListOfWorkTours() ); + tourList.addAll( person.getListOfSchoolTours() ); + tourList.addAll( person.getListOfIndividualNonMandatoryTours() ); + tourList.addAll( person.getListOfAtWorkSubtours() ); + + int tourCount = 0; + for ( TourIf tour : tourList ) { + + int modelIndex = -1; + try { + + modelIndex = modelStructure.getStopFrequencyModelIndex( tour.getTourPurpose().toLowerCase() ); + + + // write debug header + String separator = ""; + String choiceModelDescription = "" ; + String decisionMakerLabel = ""; + String loggingHeader = ""; + if( household.getDebugChoiceModels() ) { + + choiceModelDescription = String.format ( "Individual Tour Stop Frequency Choice Model:" ); + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourType=%s, TourId=%d, TourPurpose=%s.", household.getHhId(), person.getPersonNum(), person.getPersonType(), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourId(), tour.getTourPrimaryPurpose() ); + + choiceModelApplication[modelIndex].choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + loggingHeader = choiceModelDescription + " for " + decisionMakerLabel; + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + } + + + + // set the tour object + dmuObject.setTourObject(tour); + + // set the area type for the origin taz + int tableRow = zoneTableRow[tour.getTourOrigTaz()]; + dmuObject.setOriginTazAreaType( areaType[tableRow-1] ); + + // set the area type for the primary destination taz + tableRow = zoneTableRow[tour.getTourDestTaz()]; + dmuObject.setDestTazAreaType( areaType[tableRow-1] ); + + // compute the utilities + dmuObject.setDmuIndexValues( household.getHhId(), household.getHhTaz(), tour.getTourOrigTaz(), tour.getTourDestTaz() ); + + choiceModelApplication[modelIndex].computeUtilities(dmuObject, dmuObject.getDmuIndexValues() ); + + // get the random number from the household + Random random = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = random.nextDouble(); + + + // if the choice model has at least one available alternative, make choice. + int choice = -1; + if ( choiceModelApplication[modelIndex].getAvailabilityCount() > 0 ) + choice = choiceModelApplication[modelIndex].getChoiceResult( rn ); + else { + logger.error ( String.format( "Exception caught applying Individual Tour stop frequency choice model for %s type tour: j=%d, HHID=%d, personNum=%d, tourCount=%d, randomCount=%f -- no avaialable stop frequency alternative to choose.", ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], j, household.getHhId(), person.getPersonNum(), tourCount, randomCount ) ); + throw new RuntimeException(); + } + + + + // debug output + if( household.getDebugChoiceModels() ){ + + double[] utilities = choiceModelApplication[modelIndex].getUtilities(); + double[] probabilities = choiceModelApplication[modelIndex].getProbabilities(); + String[] altNames = choiceModelApplication[modelIndex].getAlternativeNames(); // 0s-indexing + + modelLogger.info( decisionMakerLabel ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("------------------ -------------- -------------- --------------"); + + double cumProb = 0.0; + for(int k=0;k 0 ) { + // get a stop purpose for each outbound stop generated, plus the stop at the primary destination + String[] obStopOrigPurposes = new String[numObStops+1]; + String[] obStopDestPurposes = new String[numObStops+1]; + int[] obStopPurposeIndices = new int[numObStops + 1]; + obStopOrigPurposes[0] = tour.getTourCategoryIsAtWork() ? "Work" : "Home"; + // the last stop record is for the trip from stop to destination + for ( int i=0; i < numObStops; i++ ) { + if ( i > 0 ) + obStopOrigPurposes[i] = obStopDestPurposes[i-1]; + obStopPurposeIndices[i] = getStopPurpose(hh, OUTBOUND_DIRECTION_NAME, tourDepartPeriod, tourPrimaryPurpose, personType); + obStopDestPurposes[i] = indexPurposeMap.get( obStopPurposeIndices[i] ); + } + obStopOrigPurposes[numObStops] = obStopDestPurposes[numObStops-1]; + obStopDestPurposes[numObStops] = tourPrimaryPurpose; + + tour.createOutboundStops( obStopOrigPurposes, obStopDestPurposes, obStopPurposeIndices ); + } + + + int numIbStops = dmuObject.getNumIbStopsAlt(stopFreqChoice); + if ( numIbStops > 0 ) { + // get a stop purpose for each inbound stop generated + String[] ibStopOrigPurposes = new String[numIbStops+1]; + String[] ibStopDestPurposes = new String[numIbStops+1]; + int[] ibStopPurposeIndices = new int[numIbStops + 1]; + ibStopOrigPurposes[0] = tourPrimaryPurpose; + // the last stop record is for the trip from stop to home or work + for ( int i=0; i < numIbStops; i++ ) { + if ( i > 0 ) + ibStopOrigPurposes[i] = ibStopDestPurposes[i-1]; + ibStopPurposeIndices[i] = getStopPurpose(hh, INBOUND_DIRECTION_NAME, tourArrivePeriod, tourPrimaryPurpose, personType); + ibStopDestPurposes[i] = indexPurposeMap.get( ibStopPurposeIndices[i] ); + } + ibStopOrigPurposes[numIbStops] = ibStopDestPurposes[numIbStops-1]; + ibStopDestPurposes[numIbStops] = tour.getTourCategoryIsAtWork() ? "Work" : "Home"; + + tour.createInboundStops( ibStopOrigPurposes, ibStopDestPurposes, ibStopPurposeIndices ); + } + + + return numObStops + numIbStops; + + } + + private void readPurposeLookupProportionsTable( String purposeLookupFilename ) { + + // read the stop purpose proportions into a TableDataSet + TableDataSet purposeLookupTable = null; + String fileName = ""; + try{ + OLD_CSVFileReader reader = new OLD_CSVFileReader(); + purposeLookupTable = reader.readFile( + new File( purposeLookupFilename ) + ); + } + catch(Exception e){ + logger.error( String.format( "Exception occurred reading stop purpose lookup proportions file: %s.", fileName ),e); + throw new RuntimeException(); + } + + + // allocate a HashMap array for each direction, dimensioned to maximum departure hour, to map keys determined by combination of categories to proportions arrays. + int start = modelStructure.getTimePeriodIndexForTime( ModelStructure.FIRST_TOD_INTERVAL_HOUR ); + int end = modelStructure.getTimePeriodIndexForTime( ModelStructure.LAST_TOD_INTERVAL_HOUR ); + int numDepartHours = end + 1; + outProportionsMaps = new HashMap[numDepartHours]; + inProportionsMaps = new HashMap[numDepartHours]; + for ( int i=start; i <= end; i++ ) { + outProportionsMaps[i] = new HashMap(); + inProportionsMaps[i] = new HashMap(); + } + + + // create a mapping between names used in lookup file and purpose names used in model + HashMap primaryPurposeMap = new HashMap(); + primaryPurposeMap.put( WORK_PURPOSE_NAME_IN_FILE, ModelStructure.WORK_PURPOSE_NAME ); + primaryPurposeMap.put( UNIVERSITY_PURPOSE_NAME_IN_FILE, ModelStructure.UNIVERSITY_PURPOSE_NAME ); + primaryPurposeMap.put( SCHOOL_PURPOSE_NAME_IN_FILE, ModelStructure.SCHOOL_PURPOSE_NAME ); + primaryPurposeMap.put( ESCORT_PURPOSE_NAME_IN_FILE, ModelStructure.ESCORT_PURPOSE_NAME ); + primaryPurposeMap.put( SHOP_PURPOSE_NAME_IN_FILE, ModelStructure.SHOPPING_PURPOSE_NAME ); + primaryPurposeMap.put( EAT_OUT_PURPOSE_NAME_IN_FILE, ModelStructure.EAT_OUT_PURPOSE_NAME ); + primaryPurposeMap.put( OTH_MAINT_PURPOSE_NAME_IN_FILE, ModelStructure.OTH_MAINT_PURPOSE_NAME ); + primaryPurposeMap.put( SOCIAL_PURPOSE_NAME_IN_FILE, ModelStructure.SOCIAL_PURPOSE_NAME ); + primaryPurposeMap.put( OTH_DISCR_PURPOSE_NAME_IN_FILE, ModelStructure.OTH_DISCR_PURPOSE_NAME ); + primaryPurposeMap.put( AT_WORK_PURPOSE_NAME_IN_FILE, ModelStructure.AT_WORK_PURPOSE_NAME ); + + + // create a mapping between stop purpose alternative indices selected from + // monte carlo process and stop purpose names used in model + // the indices are the order of the proportions columns in the table + indexPurposeMap = new HashMap(); + indexPurposeMap.put(1, "work related"); + indexPurposeMap.put(2, ModelStructure.UNIVERSITY_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(3, ModelStructure.SCHOOL_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(4, ModelStructure.ESCORT_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(5, ModelStructure.SHOPPING_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(6, ModelStructure.OTH_MAINT_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(7, ModelStructure.EAT_OUT_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(8, ModelStructure.VISITING_PRIMARY_PURPOSE_NAME); + indexPurposeMap.put(9, ModelStructure.OTH_DISCR_PRIMARY_PURPOSE_NAME); + + + // create a mapping between names used in lookup file and person type names used in model + HashMap personTypeMap = new HashMap(); + personTypeMap.put( FT_WORKER_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_FULL_TIME_WORKER_NAME ); + personTypeMap.put( PT_WORKER_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_PART_TIME_WORKER_NAME ); + personTypeMap.put( UNIVERSITY_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_UNIVERSITY_STUDENT_NAME ); + personTypeMap.put( NONWORKER_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_NON_WORKER_NAME ); + personTypeMap.put( RETIRED_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_RETIRED_NAME ); + personTypeMap.put( DRIVING_STUDENT_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_STUDENT_DRIVING_NAME ); + personTypeMap.put( NONDRIVING_STUDENT_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_STUDENT_NON_DRIVING_NAME ); + personTypeMap.put( PRESCHOOL_PERSON_TYPE_NAME, PersonIf.PERSON_TYPE_PRE_SCHOOL_CHILD_NAME ); + personTypeMap.put( ALL_PERSON_TYPE_NAME, ALL_PERSON_TYPE_NAME ); + + + + + // fields in lookup file are: + // PrimPurp Direction DepartRangeStart DepartRangeEnd Ptype Work University School Escort Shop Maintenance Eating Out Visiting Discretionary + + // populate the outProportionsMaps and inProportionsMaps arrays of maps from data in the TableDataSet. + // when stops are generated, they can lookup the proportions for stop purpose selection from a map determined + // by tour purpose, person type, outbound/inbound direction and tour departure time. From these proportions, + // a stop purpose can be drawn. + + + // loop over rows in the TableDataSet + for ( int i=0; i < purposeLookupTable.getRowCount(); i++ ) { + + // get the tour primary purpose + String tourPrimPurp = primaryPurposeMap.get( purposeLookupTable.getStringValueAt( i+1, TOUR_PRIMARY_PURPOSE_COLUMN_HEADING ) ); + + // get the half tour direction + String direction = purposeLookupTable.getStringValueAt( i+1, HALF_TOUR_DIRECTION_COLUMN_HEADING ); + + // get the beginning of the range of departure hours + int startRange = (int)purposeLookupTable.getValueAt( i+1, TOUR_DEPARTURE_START_RANGE_COLUMN_HEADING ); + int startInterval = modelStructure.getTimePeriodIndexForTime( startRange ); + + // get the end of the range of departure hours + int endRange = (int)purposeLookupTable.getValueAt( i+1, TOUR_DEPARTURE_END_RANGE_COLUMN_HEADING ); + int endInterval = modelStructure.getTimePeriodIndexForTime( endRange ); + + + // get the person type + String personType = personTypeMap.get( purposeLookupTable.getStringValueAt( i+1, PERSON_TYPE_COLUMN_HEADING ) ); + + + // columns following person type are proportions by stop purpose. Get the index of the first stop purpose proportion. + int firstPropColumn = purposeLookupTable.getColumnPosition( PERSON_TYPE_COLUMN_HEADING ) + 1; + + // starting at this column, read the proportions for all stop purposes. + // Create the array of proportions for this table record. Dimensions is size of map-1 (no atwork stop purpose). + // since indexing starts at 1, would normally add 1, but no need to add 1 to dimension (because we don't need the at-work purpose) + double[] props = new double[indexPurposeMap.size()]; + for ( int j=0; j < props.length; j++ ) { + props[j] = purposeLookupTable.getValueAt( i+1, firstPropColumn + j ); + } + + + // get a HashMap for the direction and each hour in the start/end range, and store the proportions in that map for the key. + // the key to use for any of these HashMaps is created consisting of "TourPrimPurp_PersonType" + // if the person type for the record is "All", a key is defined for each person type, and the proportions stored for each key. + if ( personType.equalsIgnoreCase( ALL_PERSON_TYPE_NAME ) ) { + for ( String ptype : personTypeMap.values() ) { + String key = tourPrimPurp + "_" + ptype; + if ( direction.equalsIgnoreCase( OUTBOUND_DIRECTION_NAME ) ) { + for ( int k=startInterval; k <= endInterval; k++ ) + outProportionsMaps[k].put(key, props); + } + else if ( direction.equalsIgnoreCase( INBOUND_DIRECTION_NAME ) ) { + for ( int k=startInterval; k <= endInterval; k++ ) + inProportionsMaps[k].put(key, props); + } + } + } + else { + String key = tourPrimPurp + "_" + personType; + if ( direction.equalsIgnoreCase( OUTBOUND_DIRECTION_NAME ) ) { + for ( int k=startInterval; k <= endInterval; k++ ) + outProportionsMaps[k].put(key, props); + } + else if ( direction.equalsIgnoreCase( INBOUND_DIRECTION_NAME ) ) { + for ( int k=startInterval; k <= endInterval; k++ ) + inProportionsMaps[k].put(key, props); + } + } + + } + + } + + + + private int getStopPurpose ( HouseholdIf household, String halfTourDirection, int todInterval, String tourPrimaryPurpose, String personType ) { + + double[] props = null; + String key = tourPrimaryPurpose + "_" + personType; + if ( halfTourDirection.equalsIgnoreCase( OUTBOUND_DIRECTION_NAME ) ) + props = outProportionsMaps[todInterval].get(key); + else if ( halfTourDirection.equalsIgnoreCase( INBOUND_DIRECTION_NAME ) ) + props = inProportionsMaps[todInterval].get(key); + + double rn = household.getHhRandom().nextDouble(); + int choice = ChoiceModelApplication.getMonteCarloSelection( props, rn ); + + // props is 0 based, so add 1 to the choice to get the true purpose index + return choice + 1; + + } + +} diff --git a/src/java/com/pb/models/ctrampIf/jppf/StopLocationModeChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/StopLocationModeChoiceModel.java new file mode 100644 index 0000000..f0c5321 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/StopLocationModeChoiceModel.java @@ -0,0 +1,1473 @@ +package com.pb.models.ctrampIf.jppf; + +import com.pb.cmap.tvpb.TapPair; +import com.pb.cmap.tvpb.TransitVirtualPathBuilder; +import com.pb.cmap.tvpb.Trip; +import com.pb.common.calculator.VariableTable; +import com.pb.common.datafile.CSVFileReader; +import com.pb.common.datafile.TableDataSet; +import com.pb.common.util.IndexSort; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.ParkingChoiceDMU; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.StopDestChoiceSize; +import com.pb.models.ctrampIf.StopIf; +import com.pb.models.ctrampIf.StopLocationDMU; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.TourIf; +import com.pb.models.ctrampIf.TourModeChoiceDMU; +import com.pb.models.ctrampIf.TripModeChoiceDMU; +import com.pb.common.newmodel.ChoiceModelApplication; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.*; +import com.pb.common.util.ResourceUtil; +import org.apache.log4j.Logger; + +/** + * This class will be used for determining the number of stops + * on individual mandatory, individual non-mandatory and joint + * tours. + * + * @author Christi Willison + * @version Nov 4, 2008 + *

+ * Created by IntelliJ IDEA. + */ +public class StopLocationModeChoiceModel implements Serializable { + + private transient Logger logger = Logger.getLogger(StopLocationModeChoiceModel.class); + private transient Logger slcLogger = Logger.getLogger("slcLogger"); + private transient Logger tripDepartLogger = Logger.getLogger("tripDepartLog"); + private transient Logger tripMcLogger = Logger.getLogger("tripMcLog"); + private transient Logger parkLocLogger = Logger.getLogger("parkLocLog"); + + private static final int HOME_TYPE_INDEX = 1; + private static final int PRIM_DEST_TYPE_INDEX = 2; + private static final int INT_STOP_TYPE_INDEX = 3; + + private static final String PROPERTIES_UEC_STOP_LOCATION = "UecFile.StopLocation"; + public static final String PROPERTIES_UEC_TRIP_MODE_CHOICE = "UecFile.TripModeChoice"; + private static final String PROPERTIES_UEC_PARKING_LOCATION_CHOICE = "UecFile.ParkingLocationChoice"; + + private static final String PROPERTIES_UEC_PARKING_LOCATION_ALTERNATIVES_FILE = "CBDParkingAlternatives.file"; + + public static final int UEC_DATA_PAGE = 0; + private static final int MAND_FREE_PAGE = 1; + private static final int MAND_PAID_PAGE = 2; + private static final int NON_MAND_PAGE = 3; + + private static int PARK_TAZ_COLUMN = 2; + + + private static final int MAX_INVALID_FIRST_ARRIVAL_COUNT = 1000; + + + private StopDestinationSampleOfAlternativesModel dcSoaModel = null; + private StopDestChoiceSize dcSizeModel = null; + + private int[] sampleValues; + private boolean[] destinationAvailability; + private int[] destinationSample; + + private TazDataIf tazDataManager; + private ModelStructure modelStructure; + + private StopLocationDMU stopLocDmuObj; + private TripModeChoiceDMU tripModeChoiceDmuObj; + private ParkingChoiceDMU parkingChoiceDmuObj; + private StopDepartArrivePeriodModel stopTodModel; + + private ChoiceModelApplication[] slChoiceModelApplication; + private ChoiceModelApplication[] mcChoiceModelApplication; + private ChoiceModelApplication mandatoryFreePc; + private ChoiceModelApplication mandatoryPaidPc; + private ChoiceModelApplication nonMandatoryPc; + + private TableDataSet cbdAltsTable; + + private int[] altToZone; + private int[] altToSubZone; + + private float[] parkRate; + + public static final int NUM_CPU_TIME_VALUES = 8; + private long soaTime; + private long slsTime; + private long slcTime; + private long todTime; + private long smcTime; + private long plcTime; + private long[] hhTimes = new long[NUM_CPU_TIME_VALUES]; + + private String loggerSeparator = ""; + + TransitVirtualPathBuilder tvpb; + + /** + * Constructor that will be used to set up the ChoiceModelApplications for each + * type of tour + * @param projectDirectory - name of root level project directory + * @param resourceBundle - properties file with paths identified + * @param dmuObject - decision making unit for stop frequency + * @param tazDataManager - holds information about TAZs in the model. + * @param modelStructure - holds the model structure info + */ + public StopLocationModeChoiceModel( HashMap propertyMap, ModelStructure modelStructure, TazDataIf tazDataManager, CtrampDmuFactoryIf dmuFactory ) { + + this.tazDataManager = tazDataManager; + this.modelStructure = modelStructure; + + setupStopLocationChoiceModels( propertyMap, dmuFactory ); + setupTripDepartTimeModel(propertyMap, dmuFactory); + setupTripModeChoiceModels( propertyMap, dmuFactory ); + setupParkingLocationModel( propertyMap, dmuFactory ); + + //create TVPB for trip mode choice UEC + tvpb = new TransitVirtualPathBuilder(propertyMap); + tvpb.setupTVPB(); + tvpb.setupModels(); + tvpb.setMTTData(tazDataManager.getMttData()); + + } + + + + + private void setupStopLocationChoiceModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( String.format( "setting up stop location choice models." ) ); + + altToZone = tazDataManager.getAltToZoneArray(); + altToSubZone = tazDataManager.getAltToSubZoneArray(); + parkRate = tazDataManager.getZonalParkRate(); + + stopLocDmuObj = dmuFactory.getStopLocationDMU(); + + + // locate the UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + // locate the UEC + String uecFileName = propertyMap.get( PROPERTIES_UEC_STOP_LOCATION ); + uecFileName = projectDirectory + uecFileName; + + + // set up the stop location choice model array + Collection modelSheets = modelStructure.getStopLocModelSheetIndices(); + slChoiceModelApplication = new ChoiceModelApplication[modelSheets.size()+1]; // one choice model for each model sheet specified + for ( int i : modelSheets ) { + if ( slChoiceModelApplication[i] == null ) + slChoiceModelApplication[i] = new ChoiceModelApplication( uecFileName, i, UEC_DATA_PAGE, propertyMap, (VariableTable)stopLocDmuObj ); + } + + + dcSizeModel = new StopDestChoiceSize(propertyMap,tazDataManager,modelStructure); + dcSoaModel = new StopDestinationSampleOfAlternativesModel(propertyMap,tazDataManager,dcSizeModel,modelStructure,dmuFactory); + + sampleValues = new int[dcSoaModel.getSampleOfAlternativesSampleSize()]; + + int altCount = tazDataManager.getNumberOfZones()*tazDataManager.getNumberOfSubZones(); + destinationAvailability = new boolean[altCount+1]; + destinationSample = new int[altCount+1]; + + + for (int i=0; i < 38; i++); + loggerSeparator += "-"; + } + + + + private void setupTripModeChoiceModels( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info( String.format( "setting up trip mode choice models." ) ); + + // locate the UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + // locate the UEC + String uecFileName = propertyMap.get( PROPERTIES_UEC_TRIP_MODE_CHOICE ); + uecFileName = projectDirectory + uecFileName; + + tripModeChoiceDmuObj = dmuFactory.getTripModeChoiceDMU(); + + // keep a set of unique model sheet numbers so that we can create ChoiceModelApplication objects once for each model sheet used + TreeSet modelIndexSet = new TreeSet(); + + Collection modelSheets = modelStructure.getTripModeChoiceModelSheetIndices(); + + int maxUecIndex = 0; + for ( int i : modelSheets ) { + modelIndexSet.add( i ); + if ( i > maxUecIndex ) + maxUecIndex = i; + } + + // set up the trip mode choice model array + mcChoiceModelApplication = new ChoiceModelApplication[maxUecIndex+1]; // one choice model for each model sheet specified + + // for each unique model index, create the ChoiceModelApplication object and the availabilty array + Iterator it = modelIndexSet.iterator(); + int i = -1; + while ( it.hasNext() ) { + i = it.next(); + mcChoiceModelApplication[i] = new ChoiceModelApplication( uecFileName, i, UEC_DATA_PAGE, propertyMap, (VariableTable)tripModeChoiceDmuObj ); + } + } + + + + private void setupParkingLocationModel( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + + logger.info ("setting up parking location choice models."); + + // locate the UEC + String projectDirectory = propertyMap.get( CtrampApplication.PROPERTIES_PROJECT_DIRECTORY ); + + // locate the UEC + String uecFileName = propertyMap.get( PROPERTIES_UEC_PARKING_LOCATION_CHOICE ); + uecFileName = projectDirectory + uecFileName; + + parkingChoiceDmuObj = dmuFactory.getParkingChoiceDMU(); + + mandatoryFreePc = new ChoiceModelApplication( uecFileName, MAND_FREE_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)parkingChoiceDmuObj ); + mandatoryPaidPc = new ChoiceModelApplication( uecFileName, MAND_PAID_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)parkingChoiceDmuObj ); + nonMandatoryPc = new ChoiceModelApplication( uecFileName, NON_MAND_PAGE, UEC_DATA_PAGE, propertyMap, (VariableTable)parkingChoiceDmuObj ); + + + + + // read the parking choice alternatives data file to get alternatives names + String cbdFile = projectDirectory + (String)propertyMap.get( PROPERTIES_UEC_PARKING_LOCATION_ALTERNATIVES_FILE ); + + try { + CSVFileReader reader = new CSVFileReader(); + cbdAltsTable = reader.readFile(new File(cbdFile)); + } + catch (IOException e) { + logger.error ("problem reading table of cbd zones for parking location choice model.", e); + System.exit(1); + } + + int[] parkTazs = cbdAltsTable.getColumnAsInt( PARK_TAZ_COLUMN ); + parkingChoiceDmuObj.setParkTazArray ( parkTazs ); + } + + private void setupTripDepartTimeModel( HashMap propertyMap, CtrampDmuFactoryIf dmuFactory ) { + stopTodModel = new StopDepartArrivePeriodModel( propertyMap, modelStructure ); + } + + + public void applyModel( HouseholdIf household ) { + + soaTime = 0; + slsTime = 0; + slcTime = 0; + todTime = 0; + smcTime = 0; + plcTime = 0; + + // get this household's person array + PersonIf[] personArray = household.getPersons(); + + // set the household id, origin taz, hh taz, and debugFlag=false in the dmus + stopLocDmuObj.setHouseholdObject(household); + tripModeChoiceDmuObj.setHouseholdObject(household); + + + // loop through the person array (1-based) + for(int j=1;j tours = new ArrayList(); + + PersonIf person = personArray[j]; + + // set the person + stopLocDmuObj.setPersonObject(person); + tripModeChoiceDmuObj.setPersonObject(person); + + + + // apply stop location and mode choice for all individual tours. + tours.addAll( person.getListOfWorkTours() ); + tours.addAll( person.getListOfSchoolTours() ); + tours.addAll( person.getListOfIndividualNonMandatoryTours() ); + tours.addAll( person.getListOfAtWorkSubtours() ); + + for ( TourIf tour : tours ) { + + // set the tour object + stopLocDmuObj.setTourObject(tour); + tripModeChoiceDmuObj.setTourObject(tour); + + + applyForOutboundStops( tour, person, household ); + + applyForInboundStops( tour, person, household ); + + } //tour loop + + } // j (person loop) + + + + // apply stop location and mode choice for all joint tours. + TourIf[] jointTours = household.getJointTourArray(); + if ( jointTours != null ) { + + for ( TourIf tour : jointTours ) { + + // set the tour object + stopLocDmuObj.setTourObject(tour); + tripModeChoiceDmuObj.setTourObject(tour); + + // no person objects for joint tours + applyForOutboundStops( tour, null, household ); + + applyForInboundStops( tour, null, household ); + + + } //tour loop + + } + + + household.setStlRandomCount( household.getHhRandomCount() ); + + + } + + + private void applyForOutboundStops( TourIf tour, PersonIf person, HouseholdIf household ) { + + StopIf[] stops = tour.getOutboundStops(); + + //select trip depart hour + if ( stops != null) { + long check = System.nanoTime(); + setOutboundTripDepartTimes ( stops ); + todTime += ( System.nanoTime() - check ); + } + + int origin = tour.getTourOrigTaz(); + int originWalkSegment = tour.getTourOrigWalkSubzone(); + int dest = tour.getTourDestTaz(); + int destWalkSegment = tour.getTourDestWalkSubzone(); + stopLocDmuObj.setInboundStop( false ); + + tripModeChoiceDmuObj.setOrigType( HOME_TYPE_INDEX ); + tripModeChoiceDmuObj.setOrigParkRate( 0.0f ); + tripModeChoiceDmuObj.setDestType( PRIM_DEST_TYPE_INDEX ); + tripModeChoiceDmuObj.setPrimDestParkRate( parkRate[dest-1] ); + + applyTripChoiceModels ( household, person, tour, stops, origin, originWalkSegment, dest, destWalkSegment, 0); + + } + + + private void applyForInboundStops( TourIf tour, PersonIf person, HouseholdIf household ) { + + StopIf[] stops = tour.getInboundStops(); + + //select trip arrive hour + if ( stops != null) { + long check = System.nanoTime(); + int lastOutboundTripDeparts = -1; + StopIf[] obStops = tour.getOutboundStops(); + if ( obStops == null ) { + lastOutboundTripDeparts = tour.getTourDepartPeriod(); + } + else { + StopIf lastStop = obStops[obStops.length - 1]; + lastOutboundTripDeparts = lastStop.getStopPeriod(); + } + + setInboundTripDepartTimes ( stops, lastOutboundTripDeparts ); + todTime += ( System.nanoTime() - check ); + } + + int origin = tour.getTourDestTaz(); + int originWalkSegment = tour.getTourDestWalkSubzone(); + int dest = tour.getTourOrigTaz(); + int destWalkSegment = tour.getTourOrigWalkSubzone(); + stopLocDmuObj.setInboundStop( true ); + + tripModeChoiceDmuObj.setOrigType( PRIM_DEST_TYPE_INDEX ); + tripModeChoiceDmuObj.setOrigParkRate( parkRate[origin-1] ); + tripModeChoiceDmuObj.setDestType( HOME_TYPE_INDEX ); + tripModeChoiceDmuObj.setPrimDestParkRate( parkRate[origin-1] ); + + applyTripChoiceModels ( household, person, tour, stops, origin, originWalkSegment, dest, destWalkSegment, 1); + + } + + + private void applyTripChoiceModels ( HouseholdIf household, PersonIf person, TourIf tour, StopIf[] stops, int origin, int originWalkSegment, int dest, int destWalkSegment, int inbound ) { + + // if there are stops on this half-tour, determine their destinations, depart hours, trip modes, and parking tazs. + if (stops != null) { + + for ( int i=0; i < stops.length; i++ ) { + + StopIf stop = stops[i]; + stop.setOrig(origin); + stop.setOrigWalkSegment(originWalkSegment); + + stopLocDmuObj.setStopObject( stop ); + + stopLocDmuObj.setStopNumber( i + 1 ); + stopLocDmuObj.setDmuIndexValues( household.getHhId(), household.getHhTaz(), origin, dest ); + + tripModeChoiceDmuObj.setStopObject( stop ); + tripModeChoiceDmuObj.setStopObjectIsFirst( i == 0 ? 1 : 0 ); + tripModeChoiceDmuObj.setStopObjectIsLast( i == stops.length - 1 ? 1 : 0 ); + + int zone = -1; + int subzone = -1; + int choice = -1; + // if not the last stop object, make a destination choice + if ( i < stops.length - 1 ) { + + tripModeChoiceDmuObj.setDestType( INT_STOP_TYPE_INDEX ); + + try { + long check = System.nanoTime(); + choice = selectDestination(stop); + slcTime += ( System.nanoTime() - check ); + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught processing %s stop location choice model for %s type tour %s stop: HHID=%d, personNum=%s, stop=%d.", ( stopLocDmuObj.getInboundStop() == 1 ? "inbound" : "outbound"), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourPrimaryPurpose(), household.getHhId(), ( person == null ? "N/A" : Integer.toString(person.getPersonNum()) ), (i+1) ) ); + throw new RuntimeException(e); + } + + zone = altToZone[choice]; + subzone = altToSubZone[choice]; + tripModeChoiceDmuObj.setIntStopParkRate( parkRate[zone-1] ); + } + else { + zone = dest; + subzone = destWalkSegment; + if ( stopLocDmuObj.getInboundStop() == 1 ) { + tripModeChoiceDmuObj.setDestType( HOME_TYPE_INDEX ); + } + else { + tripModeChoiceDmuObj.setDestType( PRIM_DEST_TYPE_INDEX ); + } + } + + stop.setDest(zone); + stop.setDestWalkSegment(subzone); + tripModeChoiceDmuObj.setDmuIndexValues( household.getHhId(), origin, zone ); + + //create TVPB for trip mode choice model + setTVPBValues(tripModeChoiceDmuObj, inbound, stop.getDestPurpose()); + + //select mode + long check = System.nanoTime(); + choice = -1; + try { + choice = selectMode( household, tour, stop ); + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught processing %s trip mode choice model for %s type tour %s intermediate stop: HHID=%d, personNum=%s, stop=%d.", ( stopLocDmuObj.getInboundStop() == 1 ? "inbound" : "outbound"), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourPrimaryPurpose(), household.getHhId(), ( person == null ? "N/A" : Integer.toString(person.getPersonNum()) ), (i+1) ) ); + e.printStackTrace(); + throw new RuntimeException(e); + } + stop.setMode( choice ); + smcTime += ( System.nanoTime() - check ); + + //set taps for stop + setStopTaps(stop, tripModeChoiceDmuObj, choice); + + // set the next segment's origin temporarily - it might change if a parking zone is selected + int tempOrigin = zone; + + check = System.nanoTime(); + float parkTot = tazDataManager.getZoneTableValue( zone, tazDataManager.getZonalParkTotFieldName() ); + + // if the stop location is in the CBD and the mode is drive (SOV or HOV), determine the parking location zone. + if ( modelStructure.getTripModeIsSovOrHov( choice ) && parkTot > 0 && tazDataManager.getZoneIsCbd( zone ) == 1 ) { + parkingChoiceDmuObj.setDmuState( household, origin, zone ); + choice = -1; + try { + choice = selectParkingLocation ( household, tour, stop ); + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught processing %s stop parking location choice model for %s type tour %s intermediate stop: HHID=%d, personNum=%s, stop=%d.", ( stopLocDmuObj.getInboundStop() == 1 ? "inbound" : "outbound"), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourPrimaryPurpose(), household.getHhId(), ( person == null ? "N/A" : Integer.toString(person.getPersonNum()) ), (i+1) ) ); + throw new RuntimeException(e); + } + stop.setPark( choice ); + tempOrigin = choice; + } + plcTime += ( System.nanoTime() - check ); + + origin = tempOrigin; + originWalkSegment = subzone; + + tripModeChoiceDmuObj.setOrigType( INT_STOP_TYPE_INDEX ); + tripModeChoiceDmuObj.setOrigParkRate( parkRate[origin-1] ); + + } + + } + // if no stops on the half-tour, determine trip mode choice, then parking location choice at the primary destination. + else { + + + long check = System.nanoTime(); + // create a Stop object for use in applying trip mode choice for this half tour without stops + String origStopPurpose = ""; + String destStopPurpose = ""; + if ( stopLocDmuObj.getInboundStop() == 0 ) { + origStopPurpose = tour.getTourCategoryIsAtWork() ? "Work" : "Home"; + destStopPurpose = tour.getTourPrimaryPurpose(); + } + else { + origStopPurpose = tour.getTourPrimaryPurpose(); + destStopPurpose = tour.getTourCategoryIsAtWork() ? "Work" : "Home"; + } + + StopIf stop = null; + try { + stop = tour.createStop( modelStructure, origStopPurpose, destStopPurpose, stopLocDmuObj.getInboundStop() == 1, tour.getTourCategoryIsAtWork() ); + } + catch ( Exception e ){ + logger.info( "exception creating stop." ); + } + + stop.setStopPeriod( stopLocDmuObj.getInboundStop() == 1 ? tour.getTourArrivePeriod() : tour.getTourDepartPeriod() ); + + stop.setOrig(origin); + stop.setOrigWalkSegment(originWalkSegment); + + stopLocDmuObj.setStopObject( stop ); + + stopLocDmuObj.setStopNumber( 1 ); + stopLocDmuObj.setDmuIndexValues( household.getHhId(), household.getHhTaz(), origin, dest ); + + int zone = dest; + int subzone = destWalkSegment; + if ( stopLocDmuObj.getInboundStop() == 1 ) { + tripModeChoiceDmuObj.setDestType( HOME_TYPE_INDEX ); + } + else { + tripModeChoiceDmuObj.setDestType( PRIM_DEST_TYPE_INDEX ); + } + + stop.setDest(zone); + stop.setDestWalkSegment(subzone); + + tripModeChoiceDmuObj.setStopObject( stop ); + tripModeChoiceDmuObj.setDmuIndexValues( household.getHhId(), origin, zone ); + + //create TVPB for trip mode choice model + setTVPBValues(tripModeChoiceDmuObj, inbound, stop.getDestPurpose()); + + //select mode + int choice = -1; + try { + choice = selectMode( household, tour, stop ); + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught processing %s trip mode choice model for %s type half-tour %s stop: HHID=%d, personNum=%s, stop=%d.", ( stopLocDmuObj.getInboundStop() == 1 ? "inbound" : "outbound"), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourPrimaryPurpose(), household.getHhId(), ( person == null ? "N/A" : Integer.toString(person.getPersonNum()) ), 1 ) ); + e.printStackTrace(); + throw new RuntimeException(e); + } + stop.setMode( choice ); + smcTime += ( System.nanoTime() - check ); + check = System.nanoTime(); + + //set taps for stop + setStopTaps(stop, tripModeChoiceDmuObj, choice); + + float parkTot = tazDataManager.getZoneTableValue( zone, tazDataManager.getZonalParkTotFieldName() ); + + // if the stop location is in the CBD and the mode is drive (SOV or HOV), determine the parking location zone. + if ( modelStructure.getTripModeIsSovOrHov( choice ) && parkTot > 0 && tazDataManager.getZoneIsCbd( zone ) == 1 ) { + parkingChoiceDmuObj.setDmuState( household, origin, zone ); + choice = -1; + try { + choice = selectParkingLocation ( household, tour, stop ); + } + catch ( Exception e ) { + logger.error ( String.format( "Exception caught processing %s stop parking location choice model for %s type half-tour %s stop: HHID=%d, personNum=%s, stop=%d.", ( stopLocDmuObj.getInboundStop() == 1 ? "inbound" : "outbound"), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourPrimaryPurpose(), household.getHhId(), ( person == null ? "N/A" : Integer.toString(person.getPersonNum()) ), 1 ) ); + throw new RuntimeException(e); + } + stop.setPark( choice ); + } + plcTime += ( System.nanoTime() - check ); + + } + + } + + + private int selectDestination(StopIf s) { + + Logger modelLogger = slcLogger; + + HouseholdIf household = s.getTour().getPersonObject().getHouseholdObject(); + TourIf tour = s.getTour(); + PersonIf person = tour.getPersonObject(); + + if ( household.getDebugChoiceModels() ) { + if ( s == null ) { + household.logHouseholdObject( "Pre Stop Location Choice for tour primary destination: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId(), modelLogger ); + household.logPersonObject( "Pre Stop Location Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Stop Location Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + } + else { + household.logHouseholdObject( "Pre Stop Location Choice for trip: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Stop_" + s.getStopId(), modelLogger ); + household.logPersonObject( "Pre Stop Location Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Stop Location Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + household.logStopObject("Pre Stop Location Choice for stop " + s.getStopId(), modelLogger, s, modelStructure ); + } + } + + + long check = System.nanoTime(); + StopDestinationSampleOfAlternativesModel.StopSoaResult result = dcSoaModel.computeDestinationSampleOfAlternatives(s); + soaTime += ( System.nanoTime() - check ); + + int numAltsInSample = result.getNumUniqueAltsInSample(); + int[] sample = result.getSample(); + float[] corrections = result.getCorrections(); + double[] stopLocSize = result.getStopLocationSize(); + + + int modelIndex = modelStructure.getStopLocationModelIndex( s.getTour().getTourPrimaryPurpose() ); + ChoiceModelApplication choiceModel = slChoiceModelApplication[modelIndex]; + + + String choiceModelDescription = ""; + String decisionMakerLabel = ""; + String loggingHeader = ""; + String separator = ""; + String logsumLoggingHeader = ""; + + if ( household.getDebugChoiceModels() ) { + + choiceModelDescription = "Stop Location Choice"; + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourPrimaryPurpose(), tour.getTourId(), s.getDestPurpose(), s.getStopId() ); + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + } + + + stopLocDmuObj.setLogSizeTerms(stopLocSize); + + Arrays.fill(destinationAvailability,false); + Arrays.fill(destinationSample,0); + for (int i=1; i <= numAltsInSample; i++) { + int alternative = sample[i]; + destinationAvailability[alternative] = true; + destinationSample[alternative] = 1; + + stopLocDmuObj.setDcSoaCorrections(altToZone[alternative],altToSubZone[alternative],corrections[i]); + + // calculate the logsum for the stop origin to the stop destination alternative + // stop origin has already been set; stop destionation is the stop alternative being considered for the ik logsum + s.setDest( altToZone[alternative] ); + s.setDestWalkSegment( altToSubZone[alternative] ); + + if ( household.getDebugChoiceModels() ) { + logsumLoggingHeader = "ik mode choice logsum for slc soa sample=" + i + ", alt=" + alternative + ", taz=" + altToZone[alternative] + ", subzone=" + altToSubZone[alternative]; + } + + + check = System.nanoTime(); + double ikLogsum = calculateTripModeChoiceLogsum( household, person, tour, s, modelLogger, logsumLoggingHeader ); + stopLocDmuObj.setTripMcLogsumIk( altToZone[alternative], altToSubZone[alternative], ikLogsum ); + + + + // calculate the logsum for the stop destination alternative to the tour primary destination + // stop destination is the tour origin or the tour primary destination, depending on whether this half-tour is inbound or outbound + s.setDest( s.isInboundStop() ? tour.getTourOrigTaz() : tour.getTourDestTaz() ); + s.setDestWalkSegment( s.isInboundStop() ? tour.getTourOrigWalkSubzone() : tour.getTourDestWalkSubzone() ); + // stop dest attributes will be reset after stop location is made; but stop origin attributes need to be reset after logsum calculation + int tempOrig = s.getOrig(); + int tempOrigWalkSegment = s.getOrigWalkSegment(); + // stop origin should be the stop alternative being considered for the jk logsum. + s.setOrig( altToZone[alternative] ); + s.setOrigWalkSegment( altToSubZone[alternative] ); + + if ( household.getDebugChoiceModels() ) { + logsumLoggingHeader = "kj mode choice logsum for slc soa sample=" + i + ", alt=" + alternative + ", taz=" + altToZone[alternative] + ", subzone=" + altToSubZone[alternative]; + } + + + double kjLogsum = calculateTripModeChoiceLogsum( household, person, tour, s, modelLogger, logsumLoggingHeader ); + s.setOrig( tempOrig ); + s.setOrigWalkSegment( tempOrigWalkSegment ); + stopLocDmuObj.setTripMcLogsumKj( altToZone[alternative], altToSubZone[alternative], kjLogsum ); + slsTime += ( System.nanoTime() - check ); + + } + + choiceModel.computeUtilities(stopLocDmuObj,stopLocDmuObj.getDmuIndexValues(),destinationAvailability,destinationSample); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( choiceModel.getAvailabilityCount() > 0 ) + chosen = choiceModel.getChoiceResult( rn ); + else { + + //set to origin or destination if no alt found, assumes 1 to 1 match alts to zone ids + chosen = rn < 0.5 ? s.getOrig() : s.getDest(); + logger.error (String.format( "Error for HHID=%d, PersonNum=%d, no available %s stop destination choice alternatives to choose from in choiceModelApplication so setting to orig or dest.", stopLocDmuObj.getHouseholdObject().getHhId(), stopLocDmuObj.getPersonObject().getPersonNum(), tour.getTourPrimaryPurpose())); + } + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() || chosen < 0 ) { + + if ( chosen < 0 ) { + choiceModelDescription = "No Alternatives for Stop Location Choice"; + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourPrimaryPurpose(), tour.getTourId(), s.getDestPurpose(), s.getStopId() ); + loggingHeader = String.format( "%s for %s", choiceModelDescription, decisionMakerLabel ); + + modelLogger.info(" "); + for (int k=0; k < loggingHeader.length(); k++) + separator += "+"; + modelLogger.info( loggingHeader ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + } + + double[] utilities = choiceModel.getUtilities(); + double[] probabilities = choiceModel.getProbabilities(); + boolean[] availabilities = choiceModel.getAvailabilities(); + + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Availability Utility Probability CumProb"); + modelLogger.info("--------------------- ------------ ----------- -------------- --------------"); + + int numberOfSubzones = tazDataManager.getNumberOfSubZones(); + + // copy the values of the sample to an array that can be sorted for logging purposes + for (int i=1; i <= numAltsInSample; i++) + sampleValues[i-1] = sample[i]; + for (int i=numAltsInSample; i < sampleValues.length; i++) + sampleValues[i] = Integer.MAX_VALUE; + int[] sortedSampleValueIndices = IndexSort.indexSort( sampleValues ); + + double cumProb = 0.0; + int selectedIndex = -1; + for(int j=1; j <= numAltsInSample; j++){ + + int k = sortedSampleValueIndices[j-1]; + int alt = sample[k+1]; + + if ( alt == chosen ) + selectedIndex = j; + + int d = ( alt-1) / numberOfSubzones + 1; + int w = alt - (d-1)*numberOfSubzones - 1; + cumProb += probabilities[alt-1]; + String altString = String.format( "%-3d %5d %5d %5d", j, alt, d, w ); + modelLogger.info(String.format("%-21s%15s%18.6e%18.6e%18.6e", altString, availabilities[alt], utilities[alt-1], probabilities[alt-1], cumProb)); + } + + modelLogger.info(" "); + int d = (chosen-1)/numberOfSubzones + 1; + int w = chosen - (d-1)*numberOfSubzones - 1; + String altString = String.format( "%-3d %5d %5d %5d", selectedIndex, chosen, d, w ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + choiceModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + choiceModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + choiceModel.logUECResults( modelLogger, loggingHeader ); + + if ( chosen < 0 ) + throw new RuntimeException(); + } + + return chosen; + } + + + private int selectMode ( HouseholdIf household, TourIf tour, StopIf stop ) { + + Logger modelLogger = tripMcLogger; + + + if ( household.getDebugChoiceModels() ) { + if ( stop == null ) { + household.logHouseholdObject( "Pre Trip Mode Choice: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId(), tripMcLogger ); + household.logPersonObject( "Pre Trip Mode Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Trip Mode Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + } + else { + household.logHouseholdObject( "Pre Trip Mode Choice: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Stop_" + stop.getStopId(), tripMcLogger ); + household.logPersonObject( "Pre Trip Mode Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Trip Mode Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + household.logStopObject("Pre Trip Mode Choice for stop " + stop.getStopId(), modelLogger, stop, modelStructure ); + } + } + + + + int modelIndex = modelStructure.getTripModeChoiceModelIndex( tour.getTourPrimaryPurpose().toLowerCase() ); + ChoiceModelApplication choiceModel = mcChoiceModelApplication[modelIndex]; + + + PersonIf person = tour.getPersonObject(); + + String choiceModelDescription = ""; + String separator = ""; + String loggerString = ""; + String decisionMakerLabel = ""; + + if ( household.getDebugChoiceModels() ) { + + choiceModelDescription = "Trip Mode Choice Model"; + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId() ); + + + modelLogger.info(" "); + loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + choiceModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + choiceModel.computeUtilities( tripModeChoiceDmuObj, tripModeChoiceDmuObj.getDmuIndexValues() ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + if ( choiceModel.getAvailabilityCount() > 0 ) + chosen = choiceModel.getChoiceResult( rn ); + + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() || chosen < 0 ) { + + double[] utilities = choiceModel.getUtilities(); + double[] probabilities = choiceModel.getProbabilities(); + + String[] altNames = choiceModel.getAlternativeNames(); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("--------------- -------------- -------------- --------------"); + + double cumProb = 0.0; + + for(int k=0; k < altNames.length; k++){ + cumProb += probabilities[k]; + String altString = String.format( "%-3d %25s", k+1, altNames[k] ); + modelLogger.info(String.format("%-30s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + + modelLogger.info(" "); + if ( chosen < 0 ) { + String altString = "No alternatives available to choose from"; + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + modelLogger.info("tour depart period=" + tour.getTourDepartPeriod() + " tour arrival period=" + tour.getTourArrivePeriod() + " stop period=" + stop.getStopPeriod()); + + if ( stop == null ) { + household.logHouseholdObject( "Pre Trip Mode Choice: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId(), tripMcLogger ); + household.logPersonObject( "Pre Trip Mode Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Trip Mode Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + } + else { + household.logHouseholdObject( "Pre Trip Mode Choice: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Stop_" + stop.getStopId(), tripMcLogger ); + household.logPersonObject( "Pre Trip Mode Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Trip Mode Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + household.logStopObject("Pre Trip Mode Choice for stop " + stop.getStopId(), modelLogger, stop, modelStructure ); + } + + } + else { + String altString = String.format( "%-3d %s", chosen, altNames[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + } + + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + choiceModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + choiceModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + choiceModel.logUECResults( modelLogger, loggerString ); + + } + + + + if ( chosen > 0 ) + return chosen; + else { + logger.error ( String.format( "HHID=%d, no available %s trip mode alternatives in tourId=%d to choose from in choiceModelApplication.", household.getHhId(), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourId() ) ); + throw new RuntimeException(); + } + + } + + + + // determine the trip mode choice logsum for the intermediate stop alternative either as an origin or a destination + private double calculateTripModeChoiceLogsum( HouseholdIf household, PersonIf person, TourIf tour, StopIf stop, Logger modelLogger, String loggerHeader ){ + + //determine the trip mode choice logsum for the sampled dest alt and store in stop location dmu + tripModeChoiceDmuObj.setDmuIndexValues( household.getHhId(), stop.getOrig(), stop.getDest() ); + tripModeChoiceDmuObj.setIntStopParkRate( parkRate[stop.getDest()-1] ); + + int mcModelIndex = modelStructure.getTripModeChoiceModelIndex( tour.getTourPrimaryPurpose().toLowerCase() ); + mcChoiceModelApplication[mcModelIndex].computeUtilities( tripModeChoiceDmuObj, tripModeChoiceDmuObj.getDmuIndexValues() ); + double logsum = mcChoiceModelApplication[mcModelIndex].getLogsum(); + + if ( household.getDebugChoiceModels() ) { + household.logStopObject(loggerHeader, modelLogger, stop, modelStructure ); + mcChoiceModelApplication[mcModelIndex].logUECResults( modelLogger, loggerHeader ); + modelLogger.info( "" ); + modelLogger.info( "calculated mc logsum: " + logsum ); + } + + return logsum; + + } + + + // this method is called to determine parking location if stop location is in the CBD and chosen mode is sov or hov. + private int selectParkingLocation ( HouseholdIf household, TourIf tour, StopIf stop ) { + + Logger modelLogger = parkLocLogger; + + if ( household.getDebugChoiceModels() ) { + if ( stop == null ) { + household.logHouseholdObject( "Pre Parking Location Choice for tour primary destination: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId(), modelLogger ); + household.logPersonObject( "Pre Parking Location Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Parking Location Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + } + else { + household.logHouseholdObject( "Pre Parking Location Choice for trip: HH_" + household.getHhId() + ", Pers_" + tour.getPersonObject().getPersonNum() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Tour_" + tour.getTourId() + ", Tour Purpose_" + tour.getTourPrimaryPurpose() + ", Stop_" + stop.getStopId(), modelLogger ); + household.logPersonObject( "Pre Parking Location Choice for person " + tour.getPersonObject().getPersonNum(), modelLogger, tour.getPersonObject() ); + household.logTourObject("Pre Parking Location Choice for tour " + tour.getTourId(), modelLogger, tour.getPersonObject(), tour ); + household.logStopObject("Pre Parking Location Choice for stop " + stop.getStopId(), modelLogger, stop, modelStructure ); + } + } + + ChoiceModelApplication choiceModel; + if ( tour.getTourCategoryIsMandatory() ) { + PersonIf person = tour.getPersonObject(); + switch ( person.getFreeParkingAvailableResult() ) { + case 1: + choiceModel = mandatoryFreePc; + break; + case 2: + choiceModel = mandatoryPaidPc; + break; + + default: + logger.error( String.format("Free parking availability choice for hh=%d was %d, but should have been 1 or 2.", household.getHhId(), person.getFreeParkingAvailableResult()) ); + throw new RuntimeException(); + } + } + else { + choiceModel = nonMandatoryPc; + } + + parkingChoiceDmuObj.setTourObject(tour); + + PersonIf person = tour.getPersonObject(); + + String choiceModelDescription = ""; + String separator = ""; + String loggerString = ""; + String decisionMakerLabel = ""; + + // log headers to traceLogger if the person making the destination choice is from a household requesting trace information + if ( household.getDebugChoiceModels() ) { + + if ( stop == null ) { + choiceModelDescription = "Parking Location Choice Model for tour primary destination"; + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourPurpose=%s, TourId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourPrimaryPurpose(), tour.getTourId() ); + } + else { + choiceModelDescription = "Parking Location Choice Model for trip"; + decisionMakerLabel = String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId() ); + } + + modelLogger.info(" "); + loggerString = choiceModelDescription + " for " + decisionMakerLabel + "."; + for (int k=0; k < loggerString.length(); k++) + separator += "+"; + modelLogger.info( loggerString ); + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + choiceModel.choiceModelUtilityTraceLoggerHeading( choiceModelDescription, decisionMakerLabel ); + + } + + + + choiceModel.computeUtilities ( parkingChoiceDmuObj, parkingChoiceDmuObj.getDmuIndexValues() ); + + Random hhRandom = household.getHhRandom(); + int randomCount = household.getHhRandomCount(); + double rn = hhRandom.nextDouble(); + + // if the choice model has at least one available alternative, make choice. + int chosen = -1; + int parkTaz = 0; + if ( choiceModel.getAvailabilityCount() > 0 ) { + chosen = choiceModel.getChoiceResult( rn ); + + // get the zone number associated with the chosen alternative + parkTaz = (int)cbdAltsTable.getValueAt( chosen, PARK_TAZ_COLUMN ); + } + + + + // write choice model alternative info to log file + if ( household.getDebugChoiceModels() || chosen < 0 ) { + + double[] utilities = choiceModel.getUtilities(); + double[] probabilities = choiceModel.getProbabilities(); + + int[] altTazs = cbdAltsTable.getColumnAsInt( PARK_TAZ_COLUMN ); + + String personTypeString = person.getPersonType(); + int personNum = person.getPersonNum(); + + modelLogger.info("Person num: " + personNum + ", Person type: " + personTypeString ); + modelLogger.info("Alternative Utility Probability CumProb"); + modelLogger.info("--------------- -------------- -------------- --------------"); + + double cumProb = 0.0; + + for(int k=0; k < altTazs.length; k++){ + int alt = altTazs[k]; + cumProb += probabilities[k]; + String altString = String.format( "%-3d %5d", k+1, alt ); + modelLogger.info(String.format("%-15s%18.6e%18.6e%18.6e", altString, utilities[k], probabilities[k], cumProb)); + } + + modelLogger.info(" "); + if ( chosen < 0 ) { + modelLogger.info( String.format("No Alternatives Available For Choice !!!" ) ); + } + else { + String altString = String.format( "%-3d %5d", chosen, altTazs[chosen-1] ); + modelLogger.info( String.format("Choice: %s, with rn=%.8f, randomCount=%d", altString, rn, randomCount ) ); + } + + modelLogger.info( separator ); + modelLogger.info( "" ); + modelLogger.info( "" ); + + + choiceModel.logAlternativesInfo ( choiceModelDescription, decisionMakerLabel ); + choiceModel.logSelectionInfo ( choiceModelDescription, decisionMakerLabel, rn, chosen ); + + + // write UEC calculation results to separate model specific log file + choiceModel.logUECResults( modelLogger, loggerString ); + + } + + + if ( chosen > 0 ) + return parkTaz; + else { + logger.error ( String.format( "Exception caught for HHID=%d, no available %s parking location alternatives in tourId=%d to choose from in choiceModelApplication.", household.getHhId(), ModelStructure.TOUR_CATEGORY_LABELS[tour.getTourCategoryIndex()], tour.getTourId() ) ); + throw new RuntimeException(); + } + + } + + + private void setOutboundTripDepartTimes ( StopIf[] stops ) { + + // these stops are in outbound direction + int halfTourDirection = 0; + + for ( int i=0; i < stops.length; i++ ) { + + // if tour depart and arrive periods are the same, set same values for the stops + StopIf stop = stops[i]; + TourIf tour = stop.getTour(); + PersonIf person = tour.getPersonObject(); + HouseholdIf household = person.getHouseholdObject(); + if ( tour.getTourArrivePeriod() == tour.getTourDepartPeriod() ) { + + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Depart Time Model Not Run Since Tour Depart and Arrive Periods are Equal; Stop Depart Period set to Tour Depart Period = " + tour.getTourDepartPeriod() + " for outbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopOrigPurpose=%s, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getOrigPurpose(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( tour.getTourDepartPeriod() ); + + } + else { + + int tripIndex = i + 1; + + if ( tripIndex == 1 ) { + + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Depart Time Model Not Run Since Trip is first trip in sequence, departing from " + stop.getOrigPurpose() + "; Stop Depart Period set to Tour Depart Period = " + tour.getTourDepartPeriod() + " for outbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopOrigPurpose=%s, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getOrigPurpose(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( tour.getTourDepartPeriod() ); + + } + else { + + int tourPrimaryPurposeIndex = tour.getTourPrimaryPurposeIndex(); + + int prevTripPeriod = stops[i-1].getStopPeriod(); + + double[] proportions = stopTodModel.getStopTodIntervalProportions(tourPrimaryPurposeIndex, halfTourDirection, prevTripPeriod, tripIndex); + + // for inbound trips, the first trip cannot arrive earlier than the last outbound trip departs + // if such a case is chosen, re-select. + int invalidCount = 0; + boolean validTripDepartPeriodSet = false; + while ( validTripDepartPeriodSet == false ) { + + double rn = household.getHhRandom().nextDouble(); + int choice = getMonteCarloSelection( proportions, rn ); + + // check that this stop depart time departs at same time or later than the stop object preceding this one in the stop sequence. + if ( choice >= prevTripPeriod && choice <= tour.getTourArrivePeriod() ) { + validTripDepartPeriodSet = true; + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Depart Time Model for outbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopOrigPurpose=%s, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getOrigPurpose(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "tourPrimaryPurposeIndex=" + tourPrimaryPurposeIndex + ", halfTourDirection=" + halfTourDirection + ", tripIndex=" + tripIndex + ", prevTripPeriod=" + prevTripPeriod ); + tripDepartLogger.info( "" ); + + tripDepartLogger.info( loggerSeparator ); + tripDepartLogger.info( String.format( "%-4s %-8s %10s %10s", "alt", "time", "prob", "cumProb" ) ); + double cumProb = 0.0; + for ( int p=1; p < proportions.length; p++ ){ + int hr = 4 + (p/2); + int min = (p%2)*30; + cumProb += proportions[p]; + String timeString = ((hr < 10) ? ("0" + hr) : ("" + hr + ":")) + ((min == 30) ? min : "00"); + tripDepartLogger.info( String.format( "%-4d %-8s %10.8f %10.8f", p, timeString, proportions[p], cumProb )); + } + tripDepartLogger.info( loggerSeparator ); + tripDepartLogger.info( "rn=" + rn + ", choice=" + choice + ", try=" + invalidCount ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( choice ); + + } + else { + invalidCount++; + } + + if ( invalidCount > MAX_INVALID_FIRST_ARRIVAL_COUNT ){ + tripDepartLogger.error( "Error in Trip Depart Time Model." ); + tripDepartLogger.error( "outbound trip depart time less than previous trip depart time or greater than tour arrive time chosen for " + invalidCount + " times." ); + tripDepartLogger.error( "Possible infinite loop?" ); + tripDepartLogger.error( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + throw new RuntimeException(); + } + + } + + } + + } + + } + + } + + private void setInboundTripDepartTimes ( StopIf[] stops, int lastOutboundTripDeparts ) { + + // these stops are in inbound direction + int halfTourDirection = 1; + + for ( int i=stops.length-1; i >= 0; i-- ) { + + // if tour depart and arrive periods are the same, set same values for the stops + StopIf stop = stops[i]; + TourIf tour = stop.getTour(); + PersonIf person = tour.getPersonObject(); + HouseholdIf household = person.getHouseholdObject(); + if ( tour.getTourArrivePeriod() == tour.getTourDepartPeriod() ) { + + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Arrive Time Model Not Run Since Tour Depart and Arrive Periods are Equal; Stop Arrive Period set to Tour Arrive Period = " + tour.getTourDepartPeriod() + " for inbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( tour.getTourArrivePeriod() ); + + } + else { + + int tripIndex = stops.length - i; + + if ( tripIndex == 1 ) { + + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Arrive Time Model Not Run Since Trip is last trip in sequence, arriving at " + stop.getDestPurpose() + "; Stop Arrive Period set to Tour Arrive Period = " + tour.getTourArrivePeriod() + " for inbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( tour.getTourArrivePeriod() ); + + } + else { + + int tourPrimaryPurposeIndex = tour.getTourPrimaryPurposeIndex(); + + int prevTripPeriod = stops[i+1].getStopPeriod(); + + double[] proportions = stopTodModel.getStopTodIntervalProportions(tourPrimaryPurposeIndex, halfTourDirection, prevTripPeriod, tripIndex); + + // for inbound trips, the first trip cannot arrive earlier than the last outbound trip departs + // if such a case is chosen, re-select. + int invalidCount = 0; + boolean validTripArrivePeriodSet = false; + while ( validTripArrivePeriodSet == false ) { + + double rn = household.getHhRandom().nextDouble(); + int choice = getMonteCarloSelection( proportions, rn ); + + // check that this stop arrival time arrives at same time or earlier than the stop object following this one in the stop sequence. + // also check that this stop arrival is after the depart time for the last outbound stop. + if ( choice <= prevTripPeriod && choice >= lastOutboundTripDeparts ) { + validTripArrivePeriodSet = true; + if ( household.getDebugChoiceModels() ) { + tripDepartLogger.info( "Trip Arrive Time Model for inbound half-tour." ); + tripDepartLogger.info( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + tripDepartLogger.info( "tourPrimaryPurposeIndex=" + tourPrimaryPurposeIndex + ", halfTourDirection=" + halfTourDirection + ", tripIndex=" + tripIndex + ", prevTripPeriod=" + prevTripPeriod ); + tripDepartLogger.info( loggerSeparator ); + tripDepartLogger.info( "" ); + + tripDepartLogger.info( String.format( "%-4s %-8s %10s %10s", "alt", "time", "prob", "cumProb" ) ); + double cumProb = 0.0; + for ( int p=1; p < proportions.length; p++ ){ + int hr = 4 + (p/2); + int min = (p%2)*30; + cumProb += proportions[p]; + String timeString = ((hr < 10) ? ("0" + hr) : ("" + hr + ":")) + ((min == 30) ? min : "00"); + tripDepartLogger.info( String.format( "%-4d %-8s %10.8f %10.8f", p, timeString, proportions[p], cumProb )); + } + tripDepartLogger.info( loggerSeparator ); + tripDepartLogger.info( "rn=" + rn + ", choice=" + choice + ", try=" + invalidCount ); + tripDepartLogger.info( "" ); + } + stop.setStopPeriod( choice ); + } + else { + invalidCount++; + } + + if ( invalidCount > MAX_INVALID_FIRST_ARRIVAL_COUNT ){ + tripDepartLogger.error( "Error in Trip Arrive Time Model." ); + tripDepartLogger.error( "First inbound trip arrival time less than last outbound trip depart time chosen for " + invalidCount + " times." ); + tripDepartLogger.error( "Possible infinite loop?" ); + tripDepartLogger.error( String.format ( "HH=%d, PersonNum=%d, PersonType=%s, TourMode=%d, TourPurpose=%s, TourId=%d, StopDestPurpose=%s, StopId=%d, inboundStopsArray Length=%d", household.getHhId(), person.getPersonNum(), person.getPersonType(), tour.getTourModeChoice(), tour.getTourPrimaryPurpose(), tour.getTourId(), stop.getDestPurpose(), stop.getStopId(), stops.length ) ); + throw new RuntimeException(); + } + + } + + } + + } + + } + + } + + /** + * + * @param probabilities has 1s based indexing + * @param randomNumber + * @return + */ + private int getMonteCarloSelection (double[] probabilities, double randomNumber) { + + int returnValue = 0; + double sum = probabilities[1]; + // probabilities array passded into this method is 1s based. + for (int i=1; i < probabilities.length-1; i++) { + if (randomNumber <= sum) { + returnValue = i; + break; + } + else { + sum += probabilities[i+1]; + returnValue = i+1; + } + } + return returnValue; + } + + public long[] getStopTimes() { + hhTimes[0] = soaTime; + hhTimes[1] = slsTime; + hhTimes[2] = slcTime - (soaTime + slsTime); + hhTimes[3] = slcTime; + hhTimes[4] = todTime; + hhTimes[5] = smcTime; + hhTimes[6] = plcTime; + + hhTimes[7] = hhTimes[3] + todTime + smcTime + plcTime; + + return hhTimes; + } + + public void cleanUp() { + dcSoaModel.cleanUp(); + } + + private void setTVPBValues(TripModeChoiceDMU tripModeChoiceDmuObj, int inbound, String purpose) { + + int NA_VALUE = 0; + final int WP_ALT = 10; + final int DL_ALT = 11; + final int DP_ALT = 12; + + Trip trip = new Trip(); + trip.setTripid(tripModeChoiceDmuObj.getTourObject().getHhId()); + trip.setOtaz(tvpb.getMTTData().getTazForMaz(tripModeChoiceDmuObj.getDmuIndexValues().getOriginZone())); + trip.setDtaz(tvpb.getMTTData().getTazForMaz(tripModeChoiceDmuObj.getDmuIndexValues().getDestZone())); + trip.setOmaz(tripModeChoiceDmuObj.getDmuIndexValues().getOriginZone()); + trip.setDmaz(tripModeChoiceDmuObj.getDmuIndexValues().getDestZone()); + trip.setAge(tripModeChoiceDmuObj.getTourObject().getPersonObject().getAge()); + trip.setCars(tripModeChoiceDmuObj.getHouseholdObject().getAutoOwnershipModelResult()); + trip.setTod(tripModeChoiceDmuObj.getTodOut()); + trip.setHhincome(tripModeChoiceDmuObj.getHouseholdObject().getIncomeInDollars()); + trip.setInbound(inbound); + trip.setDebugRecord(tripModeChoiceDmuObj.getHouseholdObject().getDebugChoiceModels()); + + trip.setWalkTimeWeight(tripModeChoiceDmuObj.getTourObject().getPersonObject().getWalkTimeWeight()); + trip.setWalkSpeed(tripModeChoiceDmuObj.getTourObject().getPersonObject().getWalkSpeed()); + trip.setMaxWalk(tripModeChoiceDmuObj.getTourObject().getPersonObject().getMaxWalk()); + trip.setValueOfTime(tripModeChoiceDmuObj.getTourObject().getPersonObject().getValueOfTime()); + + trip.setPurpose(purpose.toLowerCase().startsWith("work") ? 1 : 0); + trip.setUserClassByType("user_class_work_walk", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_work_walk")); + trip.setUserClassByType("user_class_work_pnr", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_work_pnr")); + trip.setUserClassByType("user_class_work_knr", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_work_knr")); + trip.setUserClassByType("user_class_non_work_walk", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_non_work_walk")); + trip.setUserClassByType("user_class_non_work_pnr", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_non_work_pnr")); + trip.setUserClassByType("user_class_non_work_knr", tripModeChoiceDmuObj.getTourObject().getPersonObject().getUserClass("user_class_non_work_knr")); + + //only run TVPB for the tour mode + tripModeChoiceDmuObj.setGenCostWT( NA_VALUE ); + tripModeChoiceDmuObj.setOtapWT( NA_VALUE ); + tripModeChoiceDmuObj.setDtapWT( NA_VALUE ); + tripModeChoiceDmuObj.setGenCostDL( NA_VALUE ); + tripModeChoiceDmuObj.setOtapDL( NA_VALUE ); + tripModeChoiceDmuObj.setDtapDL( NA_VALUE ); + tripModeChoiceDmuObj.setGenCostDP( NA_VALUE ); + tripModeChoiceDmuObj.setOtapDP( NA_VALUE ); + tripModeChoiceDmuObj.setDtapDP( NA_VALUE ); + + if(tripModeChoiceDmuObj.getTourMode() == WP_ALT) { + tvpb.calculatePathsForATrip(trip, true, false, false); + if(trip.getWalkTapPairs().size()>0) { + TapPair bestWalkTapPair = trip.getWalkTapPairs().get(0); //get best + tripModeChoiceDmuObj.setGenCostWT( (float) bestWalkTapPair.getTotalUtils()[0] ); + tripModeChoiceDmuObj.setOtapWT( bestWalkTapPair.otap ); + tripModeChoiceDmuObj.setDtapWT( bestWalkTapPair.dtap ); + } + } + + if(tripModeChoiceDmuObj.getTourMode() == DL_ALT) { + tvpb.calculatePathsForATrip(trip, false, false, true); + if(trip.getKnrTapPairs().size()>0) { + TapPair bestKnrTapPair = trip.getKnrTapPairs().get(0); //get best + tripModeChoiceDmuObj.setGenCostDL( (float) bestKnrTapPair.getTotalUtils()[0] ); + tripModeChoiceDmuObj.setOtapDL( bestKnrTapPair.otap ); + tripModeChoiceDmuObj.setDtapDL( bestKnrTapPair.dtap ); + } + } + + if(tripModeChoiceDmuObj.getTourMode() == DP_ALT) { + tvpb.calculatePathsForATrip(trip, false, true, false); + if(trip.getPnrTapPairs().size()>0) { + TapPair bestPnrTapPair = trip.getPnrTapPairs().get(0); //get best + tripModeChoiceDmuObj.setGenCostDP( (float) bestPnrTapPair.getTotalUtils()[0] ); + tripModeChoiceDmuObj.setOtapDP( bestPnrTapPair.otap ); + tripModeChoiceDmuObj.setDtapDP( bestPnrTapPair.dtap ); + } + } + + } + + public void setStopTaps(StopIf stop, TripModeChoiceDMU tripModeChoiceDmuObj, int choice) { + + final int WP_ALT = 10; + final int DL_ALT = 11; + final int DP_ALT = 12; + + //set taps for transit tour mode + if(choice==WP_ALT) { + stop.setBTap(tripModeChoiceDmuObj.getOtapWT()); + stop.setATap(tripModeChoiceDmuObj.getDtapWT()); + } else if (choice==DL_ALT) { + stop.setBTap(tripModeChoiceDmuObj.getOtapDL()); + stop.setATap(tripModeChoiceDmuObj.getDtapDL()); + } else if (choice==DP_ALT) { + stop.setBTap(tripModeChoiceDmuObj.getOtapDP()); + stop.setATap(tripModeChoiceDmuObj.getDtapDP()); + } + + } + +} \ No newline at end of file diff --git a/src/java/com/pb/models/ctrampIf/jppf/UsualWorkSchoolLocationChoiceModel.java b/src/java/com/pb/models/ctrampIf/jppf/UsualWorkSchoolLocationChoiceModel.java new file mode 100644 index 0000000..cbc9c1b --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/jppf/UsualWorkSchoolLocationChoiceModel.java @@ -0,0 +1,547 @@ +package com.pb.models.ctrampIf.jppf; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Serializable; + +import org.apache.log4j.Logger; +import org.jppf.client.JPPFClient; +import org.jppf.client.JPPFJob; +import org.jppf.node.protocol.DataProvider; +import org.jppf.node.protocol.MemoryMapDataProvider; +import org.jppf.node.protocol.Task; + +import com.pb.common.calculator.MatrixDataServerIf; +import com.pb.common.util.ResourceUtil; +import com.pb.models.ctrampIf.CtrampDmuFactoryIf; +import com.pb.models.ctrampIf.DestChoiceSize; +import com.pb.models.ctrampIf.HouseholdDataManagerIf; +import com.pb.models.ctrampIf.HouseholdIf; +import com.pb.models.ctrampIf.ModelStructure; +import com.pb.models.ctrampIf.PersonIf; +import com.pb.models.ctrampIf.TazDataIf; +import com.pb.models.ctrampIf.jppf.LocationChoiceTaskJppf; + +public class UsualWorkSchoolLocationChoiceModel implements Serializable { + + + private transient Logger logger = Logger.getLogger(UsualWorkSchoolLocationChoiceModel.class); + + private static final String PROPERTIES_DC_SOA_SAMPLE_SIZE = "UsualWorkAndSchoolLocationChoice.SampleOfAlternatives.SampleSize"; + private static final String PROPERTIES_UEC_USUAL_LOCATION = "UecFile.DestinationChoice"; + private static final String PROPERTIES_UEC_USUAL_LOCATION_SOA = "UecFile.SampleOfAlternativesChoice"; + private static final String PROPERTIES_UEC_TOUR_MODE_CHOICE = "UecFile.TourModeChoice"; + + private static final String PROPERTIES_RESULTS_WORK_SCHOOL_LOCATION_CHOICE = "Results.UsualWorkAndSchoolLocationChoice"; + + private static final String PROPERTIES_WORK_SCHOOL_LOCATION_CHOICE_PACKET_SIZE = "distributed.task.packet.size"; + + private static int PACKET_SIZE = 0; + + private int ONE_HH_ID = -1; + private static final String RUN_THIS_HOUSEHOLD_ONLY = "run.this.household.only"; + + + // TODO: see if we can eliminate the setup synchronization issues - otherwise the number of these small + // packets can be fine-tuned and set in properties file.. + + private static final int NUM_WRITE_PACKETS = 1000; + + private String wsLocResultsFileName; + + + private transient ResourceBundle resourceBundle; + private String projectDirectory; + + private MatrixDataServerIf ms; + private ModelStructure modelStructure; + private TazDataIf tazDataManager; + private DestChoiceSize dcSizeObj; + private CtrampDmuFactoryIf dmuFactory; + + private String dcUecFileName; + private String soaUecFileName; + private String modeChoiceUecFileName; + private int soaSampleSize; + + private String restartModelString; + + private JPPFClient jppfClient = null; + + + + + + + public UsualWorkSchoolLocationChoiceModel(ResourceBundle resourceBundle, String restartModelString, JPPFClient jppfClient, ModelStructure modelStructure, MatrixDataServerIf ms, TazDataIf tazDataManager, DestChoiceSize dcSizeObj, CtrampDmuFactoryIf dmuFactory ){ + + // set the local variables + this.resourceBundle = resourceBundle; + this.modelStructure = modelStructure; + this.tazDataManager = tazDataManager; + this.dcSizeObj = dcSizeObj; + this.dmuFactory = dmuFactory; + this.ms = ms; + this.jppfClient = jppfClient; + this.restartModelString = restartModelString; + + try { + ONE_HH_ID = Integer.parseInt( resourceBundle.getString( RUN_THIS_HOUSEHOLD_ONLY )); + } catch (MissingResourceException e) { + ONE_HH_ID=-1; + } + if (ONE_HH_ID>=0) logger.info("UWSL run.this.household.only=" + ONE_HH_ID); + + + try { + PACKET_SIZE = Integer.parseInt( resourceBundle.getString( PROPERTIES_WORK_SCHOOL_LOCATION_CHOICE_PACKET_SIZE ) ); + } + catch ( MissingResourceException e ){ + PACKET_SIZE = 0; + } + + + try { + wsLocResultsFileName = resourceBundle.getString( PROPERTIES_RESULTS_WORK_SCHOOL_LOCATION_CHOICE ); + } + catch (MissingResourceException e){ + wsLocResultsFileName = null; + } + + + projectDirectory = ResourceUtil.getProperty(resourceBundle, CtrampApplication.PROPERTIES_PROJECT_DIRECTORY); + + // get the sample-of-alternatives sample size + soaSampleSize = ResourceUtil.getIntegerProperty(resourceBundle, PROPERTIES_DC_SOA_SAMPLE_SIZE); + + // locate the UECs for destination choice, sample of alts, and mode choice + String usualLocationUecFileName = ResourceUtil.getProperty(resourceBundle, PROPERTIES_UEC_USUAL_LOCATION); + dcUecFileName = projectDirectory + usualLocationUecFileName; + + String usualLocationSoaUecFileName = ResourceUtil.getProperty(resourceBundle, PROPERTIES_UEC_USUAL_LOCATION_SOA); + soaUecFileName = projectDirectory + usualLocationSoaUecFileName; + + String tourModeChoiceUecFileName = ResourceUtil.getProperty(resourceBundle, PROPERTIES_UEC_TOUR_MODE_CHOICE); + modeChoiceUecFileName = projectDirectory + tourModeChoiceUecFileName; + + } + + + + public void runSchoolAndLocationChoiceModel (HouseholdDataManagerIf householdDataManager) { + + //runConstrainedLocationChoiceModelOriginal ( householdDataManager); + runConstrainedLocationChoiceModel ( householdDataManager); + + } + + + + /** + * + * JPPF framework based method + * @param + */ + private void runConstrainedLocationChoiceModel (HouseholdDataManagerIf householdDataManager) { + + // dimension an array to accumulate chosen long term model choices for use in shadow price adjustments + String[] tourPurposeList = modelStructure.getDcModelPurposeList( ModelStructure.MANDATORY_CATEGORY ); + + + dcSizeObj.setupDestChoiceSize( resourceBundle, projectDirectory, ModelStructure.MANDATORY_CATEGORY ); + + // calculate the size terms + if ( ! dcSizeObj.getDcSizeCalculated() ) + dcSizeObj.calculateDcSize(); + + + int[][][] originLocationsByHomeZone = householdDataManager.getTourPurposePersonsByHomeZone( tourPurposeList ); + + // balance the size variables + int start = modelStructure.getDcSizeArrayCategoryIndexOffset( ModelStructure.MANDATORY_CATEGORY ); + int end = start + modelStructure.getNumDcSizeArrayCategorySegments( ModelStructure.MANDATORY_CATEGORY ); + dcSizeObj.balanceSizeVariables(originLocationsByHomeZone, tourPurposeList, start, end); + + + HashMap propertyMap = ResourceUtil.changeResourceBundleIntoHashMap(resourceBundle); + + + + + if ( PACKET_SIZE == 0 ) + PACKET_SIZE = householdDataManager.getNumHouseholds(); + + + + + // set current iteration either to 0, or if a previously written shadow price file is specified, + // to the iteration number set in that file name +1. + int currentIter = 0; + String fileName = propertyMap.get( CtrampApplication.PROPERTIES_WORK_SCHOOL_LOCATION_CHOICE_SHADOW_PRICE_INPUT_FILE ); + if ( fileName != null ) { + dcSizeObj.restoreShadowPricingInfo( projectDirectory + fileName ); + int underScoreIndex = fileName.lastIndexOf('_'); + int dotIndex = fileName.lastIndexOf('.'); + currentIter = Integer.parseInt( fileName.substring( underScoreIndex+1, dotIndex ) ); + currentIter++; + } + + +// String restartFlag = propertyMap.get( CtrampApplication.PROPERTIES_RESTART_WITH_HOUSEHOLD_SERVER ); +// if ( restartFlag == null ) +// restartFlag = "none"; +// if ( restartFlag.equalsIgnoreCase("none") ) +// currentIter = 0; + + + + long initTime = System.currentTimeMillis(); + + + // shadow pricing iterations + for( int iter=0; iter < dcSizeObj.getMaxShadowPriceIterations(); iter++ ) { + + logger.info( "start of shadow pricing iter " + iter + ", free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + + //logger.info( String.format( "Size of Household[] in bytes = %d.", householdDataManager.getBytesUsedByHouseholdArray() ) ); + + try { + JPPFJob job = new JPPFJob(); + + ArrayList startEndTaskIndicesList = getTaskHouseholdRanges(householdDataManager, householdDataManager.getNumHouseholds() ); + + DataProvider dataProvider = new MemoryMapDataProvider(); + dataProvider.setParameter("propertyMap", propertyMap); + dataProvider.setParameter("ms", ms); + dataProvider.setParameter("modelStructure", modelStructure); + dataProvider.setParameter("tourCategory", ModelStructure.MANDATORY_CATEGORY); + dataProvider.setParameter("tazDataManager", tazDataManager); + dataProvider.setParameter("householdDataManager", householdDataManager); + dataProvider.setParameter("dcSizeObj", dcSizeObj); + dataProvider.setParameter("dcUecFileName", dcUecFileName); + dataProvider.setParameter("soaUecFileName", soaUecFileName); + dataProvider.setParameter("soaSampleSize", soaSampleSize); + dataProvider.setParameter("modeChoiceUecFileName", modeChoiceUecFileName); + dataProvider.setParameter("dmuFactory", dmuFactory); + dataProvider.setParameter("restartModelString", restartModelString); + + job.setDataProvider(dataProvider); + + int startIndex = 0; + int endIndex = 0; + int taskIndex = 1; + LocationChoiceTaskJppf myTask = null; + logger.info( "before creating tasks: free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + for ( int[] startEndIndices : startEndTaskIndicesList ) { + startIndex = startEndIndices[0]; + endIndex = startEndIndices[1]; + +// myTask = new LocationChoiceTaskJppf( propertyMap, ms, householdDataManager, modelStructure, ModelStructure.MANDATORY_CATEGORY, tazDataManager, dcSizeObj, +// dcUecFileName, soaUecFileName, soaSampleSize, modeChoiceUecFileName, dmuFactory, startIndex, endIndex ); + myTask = new LocationChoiceTaskJppf( taskIndex, startIndex, endIndex, currentIter ); + + + job.add ( myTask ); + taskIndex++; + } + + + logger.info( "after creating tasks, free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + + List> results = jppfClient.submitJob(job); + + logger.info( "after getting results, free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + + for (Task task : results) { + if (task.getException() != null) throw task.getException(); + + try { + String stringResult = (String)task.getResult(); + logger.info( stringResult ); + } + catch (Exception e) { + logger.error( "", e ); + throw new RuntimeException(); + } + + } + + } + catch (Exception e) + { + e.printStackTrace(); + } + + logger.info( "after results returned, free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + + + // sum the chosen destinations by purpose, dest zone and subzone for shadow pricing adjustment + double[][][] finalModeledDestChoiceLocationsByDestZone = householdDataManager.getMandatoryToursByDestZoneSubZone(); + + double[] numChosenDests = new double[tourPurposeList.length]; + for( int i=0; i < tourPurposeList.length; i++) { + String purposeString = tourPurposeList[i]; + int dcModelIndex = modelStructure.getDcModelPurposeIndex(purposeString); + int dcSizeArrayIndex = modelStructure.getDcSizeArrayIndexFromDcModelIndex(dcModelIndex); + for( int k=1; k < finalModeledDestChoiceLocationsByDestZone[dcSizeArrayIndex].length; k++ ) { + for( int l=0; l < finalModeledDestChoiceLocationsByDestZone[dcSizeArrayIndex][k].length; l++ ) { + numChosenDests[i] += finalModeledDestChoiceLocationsByDestZone[dcSizeArrayIndex][k][l]; + } + } + } + + logger.info( String.format("Usual work/school location choice tasks completed for shadow price iteration %d.", currentIter) ); + logger.info( String.format("Chosen dests by purpose:") ); + double total = 0; + for( int i=0; i < tourPurposeList.length; i++) { + String purposeString = tourPurposeList[i]; + logger.info( String.format("\t%-15s = %.0f", purposeString, numChosenDests[i]) ); + total += numChosenDests[i]; + } + logger.info( String.format("\t%-15s = %.0f", "total", total) ); + + + logger.info( "Usual work and school location choices elapsed time " + ((System.currentTimeMillis() - initTime) / 1000) + " seconds."); ; + + + // apply the shadow price adjustments + dcSizeObj.reportMaxDiff(currentIter, finalModeledDestChoiceLocationsByDestZone, tourPurposeList); + dcSizeObj.updateShadowPrices(finalModeledDestChoiceLocationsByDestZone, tourPurposeList); + dcSizeObj.updateSizeVariables(tourPurposeList, start, end); + dcSizeObj.updateShadowPricingInfo(currentIter, originLocationsByHomeZone, finalModeledDestChoiceLocationsByDestZone, tourPurposeList, start, end); + + householdDataManager.setUwslRandomCount( currentIter ); + + logger.info( "end of shadow pricing iter " + iter + ", free memory = " + Runtime.getRuntime().freeMemory() + ", total memory = " + Runtime.getRuntime().totalMemory() ); + + currentIter++; + + } // iter + + + /* + // done iterating, clear the dcModel objects following the final iteration. + try { + JPPFJob job = new JPPFJob(); + for ( int i=0; i < 100; i++ ){ + job.addTask( new LocationChoiceCleanupTaskJppf() ); + } + List results = client.submit(job); + for (JPPFTask task : results) { + if (task.getException() != null) throw task.getException(); + + try { + task.getResult(); + } + catch (Exception e) { + logger.error( "", e ); + throw new RuntimeException(); + } + + } + } + catch (Exception e) + { + e.printStackTrace(); + } + */ + + + //jppfClient.close(); + + + + logger.info( "Usual work and school location choices computed in " + ((System.currentTimeMillis() - initTime) / 1000) + " seconds."); ; + + } + + + + /** + * Loops through the households in the HouseholdDataManager, gets the households and persons + * and writes a row with detail on each of these in a file. + * + * @param householdDataManager is the object from which the array of household objects can be retrieved. + * @param projectDirectory is the root directory for the output file named + */ + public void saveResults( HouseholdDataManagerIf householdDataManager, String projectDirectory, int globalIteration ){ + + FileWriter writer; + PrintWriter outStream = null; + + if ( wsLocResultsFileName != null ) { + + // insert '_' and the global iteration number at end of filename or before '.' if there is a file extension in the name. + int dotIndex = wsLocResultsFileName.indexOf('.'); + if ( dotIndex < 0 ) { + wsLocResultsFileName = String.format( "%s_%d", wsLocResultsFileName, globalIteration ); + } + else { + String base = wsLocResultsFileName.substring( 0, dotIndex ); + String extension = wsLocResultsFileName.substring( dotIndex ); + wsLocResultsFileName = String.format( "%s_%d%s", base, globalIteration, extension ); + } + + + + wsLocResultsFileName = projectDirectory + wsLocResultsFileName; + + try { + writer = new FileWriter(new File(wsLocResultsFileName)); + outStream = new PrintWriter (new BufferedWriter( writer ) ); + } + catch(IOException e){ + logger.fatal( String.format( "Exception occurred opening wsLoc results file: %s.", wsLocResultsFileName) ); + throw new RuntimeException(e); + } + + + // write header + outStream.println( "HHID,HomeTAZ,HomeSubZone,PersonID,PersonNum,PersonWorkOcc,PersonType,PersonAge,EmploymentCategory,StudentCategory,WorkLocIndex,WorkLocation,WorkSubZone,SchlLocIndex,SchoolLocation,SchoolSubZone"); + + + ArrayList startEndTaskIndicesList = getWriteHouseholdRanges(householdDataManager, householdDataManager.getNumHouseholds() ); + + for ( int[] startEndIndices : startEndTaskIndicesList ) { + + int startIndex = startEndIndices[0]; + int endIndex = startEndIndices[1]; + + // get the array of households + HouseholdIf[] householdArray = householdDataManager.getHhArray( startIndex, endIndex ); + + for(int i=0; i < householdArray.length; ++i){ + + HouseholdIf household = householdArray[i]; + + int hhId = household.getHhId(); + int homeTaz = household.getHhTaz(); + int homeSubzone = household.getHhWalkSubzone(); + + PersonIf[] personArray = household.getPersons(); + + for (int j = 1; j < personArray.length; ++j) { + + PersonIf person = personArray[j]; + + int personId = person.getPersonId(); + int personNum = person.getPersonNum(); + String personType = person.getPersonType(); + int personAge = person.getAge(); + String employmentCategory = person.getPersonEmploymentCategory(); + String studentCategory = person.getPersonStudentCategory(); + int workLocIndex = person.getWorkLocationPurposeIndex(); + int schlLocIndex = person.getSchoolLocationPurposeIndex(); + int personWorkOcc = person.getPersonWorkerOccupation(); + + int workLocation = person.getUsualWorkLocation(); + int workSubZone = person.getPersonWorkLocationSubZone(); + + int schoolLocation = person.getUsualSchoolLocation(); + int schoolSubZone = person.getPersonSchoolLocationSubZone(); + + // write data record + outStream.println( String.format("%d,%d,%d,%d,%d,%d,%s,%d,%s,%s,%d,%d,%d,%d,%d,%d" , + hhId, homeTaz, homeSubzone, personId, personNum, personWorkOcc, personType, personAge, + employmentCategory, studentCategory, + workLocIndex, workLocation, workSubZone, schlLocIndex, schoolLocation, schoolSubZone)); + + } + + } + + } + + + outStream.close(); + } + + } + + + private ArrayList getTaskHouseholdRanges(HouseholdDataManagerIf hhDataManager, int numberOfHouseholds ) { + + ArrayList startEndIndexList = new ArrayList(); + + if ( ONE_HH_ID < 0 ) { + + int startIndex = 0; + int endIndex = 0; + while ( endIndex < numberOfHouseholds - 1 ) { + endIndex = startIndex + PACKET_SIZE - 1; + if ( endIndex + PACKET_SIZE > numberOfHouseholds ) + endIndex = numberOfHouseholds - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += PACKET_SIZE; + } + + return startEndIndexList; + } + else { + + // create a single task packet high one household id + int[] startEndIndices = new int[2]; + int index = hhDataManager.getArrayIndex( ONE_HH_ID ); + startEndIndices[0] = index; + startEndIndices[1] = index; + startEndIndexList.add( startEndIndices ); + + return startEndIndexList; + + } + + } + + private ArrayList getWriteHouseholdRanges(HouseholdDataManagerIf hhDataManager, int numberOfHouseholds ) { + + ArrayList startEndIndexList = new ArrayList(); + + if ( ONE_HH_ID < 0 ) { + + int startIndex = 0; + int endIndex = 0; + + while ( endIndex < numberOfHouseholds - 1 ) { + endIndex = startIndex + NUM_WRITE_PACKETS - 1; + if ( endIndex + NUM_WRITE_PACKETS > numberOfHouseholds ) + endIndex = numberOfHouseholds - 1; + + int[] startEndIndices = new int[2]; + startEndIndices[0] = startIndex; + startEndIndices[1] = endIndex; + startEndIndexList.add( startEndIndices ); + + startIndex += NUM_WRITE_PACKETS; + } + + return startEndIndexList; + } + else { + + // create a single task packet high one household id + int[] startEndIndices = new int[2]; + int index = hhDataManager.getArrayIndex( ONE_HH_ID ); + startEndIndices[0] = index; + startEndIndices[1] = index; + startEndIndexList.add( startEndIndices ); + + return startEndIndexList; + + } + + } + +} diff --git a/src/java/com/pb/models/ctrampIf/sqlite/ConnectionHelper.java b/src/java/com/pb/models/ctrampIf/sqlite/ConnectionHelper.java new file mode 100644 index 0000000..da7eb2c --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/sqlite/ConnectionHelper.java @@ -0,0 +1,46 @@ +package com.pb.models.ctrampIf.sqlite; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + + +public class ConnectionHelper { + + private String url; + private static ConnectionHelper instance; + + private ConnectionHelper( String fileName ) + { + try { + Class.forName( "org.sqlite.JDBC" ); + //url = "jdbc:sqlite:/c:/jim/projects/baylanta/data/status.db"; + url = "jdbc:sqlite:/" + fileName; + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static Connection getConnection( String fileName ) throws SQLException { + if (instance == null) { + instance = new ConnectionHelper( fileName ); + } + try { + return DriverManager.getConnection(instance.url); + } catch (SQLException e) { + throw e; + } + } + + public static void close(Connection connection) + { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/java/com/pb/models/ctrampIf/sqlite/DAOException.java b/src/java/com/pb/models/ctrampIf/sqlite/DAOException.java new file mode 100644 index 0000000..2b25e42 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/sqlite/DAOException.java @@ -0,0 +1,22 @@ +package com.pb.models.ctrampIf.sqlite; + +public class DAOException extends RuntimeException +{ + static final long serialVersionUID = -1881205326938716446L; + + public DAOException(String message) + { + super(message); + } + + public DAOException(Throwable cause) + { + super(cause); + } + + public DAOException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/src/java/com/pb/models/ctrampIf/sqlite/SqliteService.java b/src/java/com/pb/models/ctrampIf/sqlite/SqliteService.java new file mode 100644 index 0000000..f5e5582 --- /dev/null +++ b/src/java/com/pb/models/ctrampIf/sqlite/SqliteService.java @@ -0,0 +1,103 @@ +package com.pb.models.ctrampIf.sqlite; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + + +public class SqliteService { + + Connection c = null; + String databaseFile; + + public void connect( String fileName, String tableName ) throws DAOException { + + try { + c = ConnectionHelper.getConnection( fileName ); + Statement s = c.createStatement(); + + s.execute("CREATE TABLE IF NOT EXISTS " + tableName + " (" + + " id INTEGER, " + + " numProcessed INTEGER, " + + " totalToProcess INTEGER, " + + " startUp INTEGER, " + + " runTime INTEGER, " + + " shutDown INTEGER " + + ")" ); + + s.execute("DELETE FROM " + tableName); + + + } catch (SQLException e) { + e.printStackTrace(); + throw new DAOException(e); + } + + } + + + public void listRecords( String tableName ) throws DAOException { + + try { + + Statement s = c.createStatement(); + + ResultSet rs = s.executeQuery("SELECT id, numProcessed, totalToProcess, startUp, runTime, shutDown FROM " + tableName + " ORDER BY id"); + while (rs.next()) { + System.out.println( rs.getInt("id") + ", " + rs.getInt("numProcessed") + ", " + rs.getInt("totalToProcess") + ", " + rs.getInt("startUp") + ", " + rs.getInt("runTime") + ", " + rs.getInt("shutDown") ); + } + + } catch (SQLException e) { + e.printStackTrace(); + throw new DAOException(e); + } + + } + + + public void insertRecord( String tableName, int id, int numProcessed, int totalToProcess, int startUp, int runTime, int shutDown) throws DAOException { + + try { + + Statement s = c.createStatement(); + String query = String.format("INSERT INTO %s (id, numProcessed, totalToProcess, startUp, runTime, shutDown) VALUES (%d, %d, %d, %d, %d, %d)", tableName, id, numProcessed, totalToProcess, startUp, runTime, shutDown); + s.execute( query ); + + } catch (SQLException e) { + e.printStackTrace(); + throw new DAOException(e); + } + + } + + + public void updateRecord( String tableName, int id, int numProcessed, int totalToProcess, int startUp, int runTime, int shutDown) throws DAOException { + + try { + + Statement s = c.createStatement(); + String query = String.format("UPDATE %s SET numProcessed=%d, totalToProcess=%d, startUp=%d, runTime=%d, shutDown=%d WHERE id=%d", tableName, numProcessed, totalToProcess, startUp, runTime, shutDown, id); + s.execute( query ); + + } catch (SQLException e) { + e.printStackTrace(); + throw new DAOException(e); + } + + } + + + public static void main(String[] args) { + + SqliteService s = new SqliteService(); + s.connect( "c:/jim/status.db", "uwsl" ); + + s.insertRecord( "uwsl", 0, 27, 1250, 99, 102, 10 ); + s.insertRecord( "uwsl", 2, 29, 1250, 58, 101, 9 ); + s.insertRecord( "uwsl", 1, 32, 1250, 77, 99, 8 ); + s.listRecords( "uwsl" ); + + } + +}