/* Domestic Active Occupancy Model - Simulation Example Code Copyright (C) 2008 Ian Richardson, Murray Thomson CREST (Centre for Renewable Energy Systems Technology), Department of Electronic and Electrical Engineering Loughborough University, Leicestershire LE11 3TU, UK Tel. +44 1509 635326. Email address: I.W.Richardson@lboro.ac.uk Java Implementation (c) 2014 James Keirstead Imperial College London j.keirstead@imperial.ac.uk This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.imperial.simelec; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import au.com.bytecode.opencsv.CSVReader; import au.com.bytecode.opencsv.CSVWriter; /** * Simulates the number of active occupants within a household for a single day * at ten-minute intervals. * * @author James Keirstead * */ public class OccupancyModel { // Class variables private int nResidents; private boolean weekend; private String out_dir; private File out_file; private boolean has_run = false; // Data variables private static String start_states_weekend = "/data/occ_start_states_weekend.csv"; private static String start_states_weekday = "/data/occ_start_states_weekday.csv"; private static String template = "/data/tpm_%d_%s.csv"; /** * Simulates the number of active occupants within a household for a single * day at ten-minute intervals. * * @param args * a String array specifying the number of residents, a * two-letter code for weekend (<code>we</code>) or weekday ( * <code>wd</code>), and a String giving the output directory for * the results. An optional fourth argument can be specified, an * int giving a random number seed. If these are not specified, * the default is to simulate two occupants for a weekday with * results saved in the current directory. */ public static void main(String[] args) { int residents; boolean weekend; String output_dir; // Check the inputs if (args.length == 3 || args.length == 4) { residents = Integer.valueOf(args[0]); weekend = args[1].equals("we") ? true : false; output_dir = args[2]; if (args.length == 4) { DiscretePDF.setSeed(Integer.valueOf(args[3])); } } else { System.out.printf( "%d arguments detected. Using default arguments.%n", args.length); residents = 2; weekend = false; output_dir = "."; } // Build the model OccupancyModel model = new OccupancyModel(residents, weekend, output_dir); // Run the model try { model.run(); } catch (IOException e) { e.printStackTrace(); } } /** * Create a new OccupancyModel with a specified number of residents, * simulation day, and output directory * * @param residents * an int between 1 and 5 giving the number of residents * @param weekend * a boolean indicating whether to simulate a weekday ( * <code>false</code>) or weekend (<code>true</code>) * @param dir * a String giving the output directory */ public OccupancyModel(int residents, boolean weekend, String dir) { this.nResidents = SimElec.validateResidents(residents); this.weekend = weekend; this.out_dir = dir; this.out_file = OccupancyModel.getOutputFile(dir); } /** * Gets the preferred output file for an OccupancyModel running in a specified directory. * * @param dir the output directory * @return the output File */ protected static File getOutputFile(String dir) { return new File(dir, "occupancy_output.csv"); } /** * Simulate the number of active occupants in a domestic dwelling for a * single day at ten-minute intervals. * * @throws IOException */ public void run() throws IOException { // System.out.print("Running occupancy model..."); // Ensure the output directory exists File dir = new File(this.out_dir); if (!dir.isDirectory()) dir.mkdirs(); // Step 2: Determine the active occupancy start state between 00:00 and // 00:10 // Load in the start state data from occ_start_states String filename = weekend ? start_states_weekend : start_states_weekday; InputStream is = this.getClass().getResourceAsStream(filename); CSVReader reader = new CSVReader(new InputStreamReader(is), ',', '\'', 2); List<String[]> myEntries = reader.readAll(); reader.close(); double[] vector = new double[myEntries.size()]; // vector = n rows int j = 0; for (String[] s : myEntries) { vector[j] = Float.valueOf(s[nResidents]); j++; } // Draw from the cumulative distribution DiscretePDF pdf = new DiscretePDF(vector); int initialState = pdf.getRandomIndex(); // Step 3: Determine the active occupancy transitions for each ten // minute period of the day. // First load in the correct file filename = String.format(template, nResidents, weekend ? "weekend" : "weekday"); is = this.getClass().getResourceAsStream(filename); reader = new CSVReader(new InputStreamReader(is), ',', '\'', 1); myEntries = reader.readAll(); reader.close(); // Create a list to save the results List<String[]> results = new ArrayList<String[]>(144); String[] tmp = { "1", String.valueOf(initialState) }; results.add(tmp); // Already have initial state; so iterate over remaining entries for (int t = 1; t < 144; t++) { // First calculate the row int rowID = (t - 1) * 7 + initialState; String[] row = myEntries.get(rowID); // Grab the vector of transition probabilities vector = new double[row.length - 2]; for (int i = 2; i < row.length - 2; i++) { vector[i - 2] = Float.valueOf(row[i]); } // Draw for the probability pdf = new DiscretePDF(vector); int newState = pdf.getRandomIndex(); String[] tmp2 = { String.valueOf(t + 1), String.valueOf(newState) }; results.add(tmp2); initialState = newState; } // Save the result to a CSV file CSVWriter writer = new CSVWriter(new FileWriter(out_file), ',', '\0'); writer.writeAll(results); writer.close(); has_run = true; // System.out.println("done."); } /** * Retrieves occupancy data calculated by this OccupancyModel. * * @return an array of 144 int values giving the occupancy at ten-minute * intervals during the day * @throws IOException */ public int[] getOccupancy() throws IOException { if (!has_run) this.run(); CSVReader reader = new CSVReader(new FileReader(out_file)); List<String[]> myEntries = reader.readAll(); reader.close(); int[] result = new int[myEntries.size()]; for (int i = 0; i < myEntries.size(); i++) { result[i] = Integer.valueOf(myEntries.get(i)[1]); } return (result); } }