View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.experiment.results;
17  
18  import java.io.File;
19  import java.io.FileWriter;
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  
28  import p3j.gui.panels.projections.ParameterInstanceNode;
29  import p3j.misc.Misc;
30  import p3j.pppm.ProjectionModel;
31  import p3j.pppm.parameters.ParameterAssignment;
32  import p3j.pppm.parameters.ParameterAssignmentComparator;
33  import p3j.pppm.parameters.ParameterInstance;
34  import p3j.pppm.parameters.ParameterInstanceComparator;
35  import p3j.pppm.sets.Set;
36  import p3j.pppm.sets.SetType;
37  
38  /**
39   * Auxiliary class to encode assumption mappings and describe the encoding in
40   * human- and machine-readable form. Both
41   * {@link ParameterAssumptionEncoder#orderedParameterInstances} and
42   * {@link ParameterAssumptionEncoder#encoding} are necessary: the first item
43   * gives the order in which the assumptions allocated to the parameter instances
44   * are given, the second defines which index belongs to which assumption. For
45   * example, the encoded assumption sequence
46   * 
47   * [0 2 3]
48   * 
49   * can be used to read out a specific allocation as follows:
50   * 
51   * 1. The parameter instance in question is the last item in
52   * {@link ParameterAssumptionEncoder#orderedParameterInstances}, so the selected
53   * assumption here is '3'
54   * 
55   * 2. For this parameter instance, the index '3' refers to a specific parameter
56   * assignment.
57   * 
58   * This mapping is summarised in both human- and machine-readable form.
59   * 
60   * The order of the instances is defined by {@link ParameterInstanceComparator}.
61   * The order of assignments is defined by their IDs.
62   * 
63   * @see ParameterAssignment
64   * @see ParameterInstance
65   * @see ParameterInstanceComparator
66   * 
67   * @author Christina Bohk
68   * @author Roland Ewald
69   * 
70   */
71  public class ParameterAssumptionEncoder {
72  
73  	/** The given projection. */
74  	private final ProjectionModel projection;
75  
76  	/** The ordered sequence of parameter instances. */
77  	private final List<ParameterInstance> orderedParameterInstances;
78  
79  	/** The encoding parameter instance ID => (parameter assignment ID => index). */
80  	private final Map<Integer, Map<Integer, Integer>> encoding;
81  
82  	/** Auxiliary data structure: ID => parameter assignment. */
83  	private final Map<Integer, ParameterAssignment> assignments = new HashMap<Integer, ParameterAssignment>();
84  
85  	/**
86  	 * Instantiates a new parameter assumption encoder.
87  	 * 
88  	 * @param projectionModel
89  	 *          the projection model
90  	 */
91  	public ParameterAssumptionEncoder(ProjectionModel projectionModel) {
92  		projection = projectionModel;
93  		orderedParameterInstances = setUpOrderedInstanceList();
94  		encoding = constructEncoding();
95  	}
96  
97  	/**
98  	 * Sets the up ordered instance list.
99  	 * 
100 	 * @return the list< parameter instance>
101 	 */
102 	private List<ParameterInstance> setUpOrderedInstanceList() {
103 		List<ParameterInstance> paramInstances = new ArrayList<ParameterInstance>(
104 		    projection.getAllParameterInstances());
105 		Collections.sort(paramInstances, new ParameterInstanceComparator());
106 		return Collections.unmodifiableList(paramInstances);
107 	}
108 
109 	/**
110 	 * Constructs the encoding.
111 	 * 
112 	 * @return the map containing the encoding
113 	 */
114 	private Map<Integer, Map<Integer, Integer>> constructEncoding() {
115 		Map<Integer, Map<Integer, Integer>> paramEncoding = new HashMap<Integer, Map<Integer, Integer>>();
116 
117 		Map<ParameterInstance, SetType> instSetTypeMap = projection
118 		    .getInstanceSetTypes();
119 		for (ParameterInstance instance : orderedParameterInstances) {
120 			paramEncoding.put(instance.getID(),
121 			    getSubEncoding(instSetTypeMap, instance));
122 		}
123 
124 		return Collections.unmodifiableMap(paramEncoding);
125 	}
126 
127 	/**
128 	 * Constructs the encoding for a certain parameter instance.
129 	 * 
130 	 * @param instSetTypeMap
131 	 *          the map from parameter instances to Settypes
132 	 * @param instance
133 	 *          the given parameter instance
134 	 * 
135 	 * @return the sub-encoding
136 	 */
137 	private Map<Integer, Integer> getSubEncoding(
138 	    Map<ParameterInstance, SetType> instSetTypeMap, ParameterInstance instance) {
139 
140 		List<ParameterAssignment> assignmentList = getAllAssignmentsForInstance(
141 		    instSetTypeMap, instance);
142 
143 		Collections.sort(assignmentList, new ParameterAssignmentComparator());
144 
145 		Map<Integer, Integer> subEncoding = new HashMap<Integer, Integer>();
146 		int assignmentCounter = 0;
147 		for (ParameterAssignment assignment : assignmentList) {
148 			assignments.put(assignment.getID(), assignment);
149 			subEncoding.put(assignment.getID(), assignmentCounter++);
150 		}
151 
152 		return Collections.unmodifiableMap(subEncoding);
153 	}
154 
155 	/**
156 	 * Gets the all assignments for a parameter instance.
157 	 * 
158 	 * @param instSetTypeMap
159 	 *          the instance to Settype map
160 	 * @param instance
161 	 *          the parameter instance
162 	 * 
163 	 * @return the all assignments for the instance
164 	 */
165 	private List<ParameterAssignment> getAllAssignmentsForInstance(
166 	    Map<ParameterInstance, SetType> instSetTypeMap, ParameterInstance instance) {
167 		SetType setType = instSetTypeMap.get(instance);
168 		List<ParameterAssignment> assignmentList = new ArrayList<ParameterAssignment>();
169 		for (Set set : setType.getSets()) {
170 			assignmentList.addAll(set.getParameterAssignments(instance)
171 			    .getAssignments());
172 		}
173 		return assignmentList;
174 	}
175 
176 	/**
177 	 * Writes a mapping summary. Basically the contents of
178 	 * {@link ParameterAssumptionEncoder#encoding}, ordered by
179 	 * {@link ParameterAssumptionEncoder#orderedParameterInstances}.
180 	 * 
181 	 * @param dataDirectory
182 	 *          the data directory
183 	 * 
184 	 * @throws IOException
185 	 *           Signals that an I/O exception has occurred.
186 	 */
187 	public void writeMappingSummary(File dataDirectory) throws IOException {
188 
189 		StringBuffer strBuf = new StringBuffer();
190 		for (ParameterInstance instance : orderedParameterInstances) {
191 			strBuf.append(ParameterInstanceNode.getDisplayName(instance) + "  ["
192 			    + instance.getID() + "]:\n");
193 			Map<Integer, Integer> assignmentMap = encoding.get(instance.getID());
194 			Map<Integer, Integer> inverted = new HashMap<Integer, Integer>();
195 			Misc.invertMap(assignmentMap, inverted);
196 			for (int i = 0; i < inverted.size(); i++) {
197 				int id = inverted.get(i);
198 				ParameterAssignment assignment = assignments.get(id);
199 				strBuf.append("\t" + i + ": " + assignment.getName() + " [" + id
200 				    + "]\n");
201 			}
202 			strBuf.append("\n\n");
203 		}
204 
205 		FileWriter fw = new FileWriter(dataDirectory.getAbsolutePath()
206 		    + File.separatorChar + "assumption_mapping.txt");
207 		fw.append(strBuf);
208 		fw.close();
209 
210 	}
211 
212 	/**
213 	 * Encode a given instance -> assignment mapping to array.
214 	 * 
215 	 * @param assignment
216 	 *          the assignment mapping
217 	 * 
218 	 * @return the encoded mapping
219 	 */
220 	public int[] encode(Map<ParameterInstance, ParameterAssignment> assignment) {
221 		int[] result = new int[orderedParameterInstances.size()];
222 		Map<Integer, Integer> idMapping = convertToIDMapping(assignment);
223 		for (int i = 0; i < result.length; i++) {
224 			ParameterInstance instance = orderedParameterInstances.get(i);
225 			result[i] = encoding.get(instance.getID()).get(
226 			    idMapping.get(instance.getID()));
227 		}
228 		return result;
229 	}
230 
231 	/**
232 	 * Converts given assignment to an instance id => assignment id mapping.
233 	 * 
234 	 * @param assignment
235 	 *          the assignment
236 	 * 
237 	 * @return the corresponding mapping among IDs
238 	 */
239 	private Map<Integer, Integer> convertToIDMapping(
240 	    Map<ParameterInstance, ParameterAssignment> assignment) {
241 		Map<Integer, Integer> result = new HashMap<Integer, Integer>();
242 		for (Entry<ParameterInstance, ParameterAssignment> aEntry : assignment
243 		    .entrySet()) {
244 			result.put(aEntry.getKey().getID(), aEntry.getValue().getID());
245 		}
246 		return result;
247 	}
248 
249 	/**
250 	 * Returns a verbose encoding of a given assignment.
251 	 * 
252 	 * @param assignment
253 	 *          the assignment
254 	 * 
255 	 * @return the verbose encoding
256 	 */
257 	public String verboseEncoding(
258 	    Map<ParameterInstance, ParameterAssignment> assignment) {
259 		StringBuffer strBuf = new StringBuffer();
260 		Map<Integer, Integer> idMapping = convertToIDMapping(assignment);
261 		for (int i = 0; i < orderedParameterInstances.size(); i++) {
262 			ParameterInstance instance = orderedParameterInstances.get(i);
263 			int assignmentID = idMapping.get(instance.getID());
264 			strBuf.append(ParameterInstanceNode.getDisplayName(instance) + ":\n\t"
265 			    + assignments.get(assignmentID).getName() + " [option:"
266 			    + encoding.get(instance.getID()).get(assignmentID) + "]\n");
267 		}
268 		return strBuf.toString();
269 	}
270 }