ContentsIndexHome
PreviousUpNext
Java Peformance example

The Performance example in Java.

  1: package com.aimms.aimmssdk.examples.performance;
  2: 
  3: import com.aimms.aimmssdk.*;
  4: import java.util.Date;
  5: import org.slf4j.Logger;
  6: import org.slf4j.LoggerFactory;
  7: 
  8: /**
  9:  * This example demonstrates the performance difference between three ways to
 10:  * assign data to a set and to assign a 3 dimensional parameter on 50% of its
 11:  * domain positions.
 12:  */
 13: class Performance {
 14: 
 15:     static private Logger logger = LoggerFactory.getLogger(Performance.class);
 16:     String m_Location;
 17:     String m_Project;
 18:     String[] m_Labels;
 19:     ISession m_Aimms = null;
 20:     ISetData m_SubSet = null;
 21:     IMultiDimData m_LargePar = null;
 22:     long m_StartTime = 0;
 23: 
 24:     public Performance(String aimmsLocation, String project, String[] labels) {
 25:         m_Location = aimmsLocation;
 26:         m_Project = project;
 27:         m_Labels = labels;
 28:     }
 29: 
 30:     /**
 31:      * The convenient way: Use a Tuple object constructed with labels to insert
 32:      * each data entry. This is inefficient due to the required string
 33:      * comparisons.
 34:      */
 35:     public void convenientAssignLabels() {
 36: 
 37:         openSessionAndData();
 38:         int setsize = m_Labels.length;
 39: 
 40:         start("Assign string labels using insert and the Tuple class");
 41: 
 42:         double value = 0.0;
 43: 
 44:         for (int i = 0; i < setsize; i += 2) {  // a density  of 50%, skip all odd positions of this dimension
 45:             for (int j = 0; j < setsize; ++j) {
 46:                 for (int k = 0; k < setsize; ++k) {
 47:                     ++value;
 48:                     m_LargePar.insert(new Tuple(m_Labels[i], m_Labels[j], m_Labels[k]), value);
 49:                 }
 50:             }
 51:         }
 52:         m_Aimms.updateData();
 53: 
 54:         stop();
 55: 
 56:         closeDataAndSession();
 57:     }
 58: 
 59:     /**
 60:      * Ordinals, ITuple and setValue: The more efficient way: Use ordinals to
 61:      * construct an ITuple and add the datapoint with it. Since the SDK uses the
 62:      * 'natural' Aimms ordering, the ordering of the data is not guaranteed to
 63:      * be the order in which the set data is supplied. So use ordinals with
 64:      * care. See also the section on "Set element ordering" in the Execution
 65:      * Efficiency Cookbook chapter in the Aimms Language Reference.
 66:      */
 67:     public void efficientAssignLabels() {
 68: 
 69:         openSessionAndData();
 70:         int setsize = m_Labels.length;
 71: 
 72:         start("Assign string labels first to the set and use the ITuple interface, ordinals and setValue to assign the values on the parameter");
 73: 
 74: 
 75:         for (int i = 0; i < setsize; ++i) {
 76:             m_SubSet.add(m_Labels[i]);
 77:         }
 78: 
 79:         m_Aimms.updateData(); // Update the set data to make label lookup faster.
 80: 
 81:         ITuple tup = m_LargePar.createTuple();
 82:         double value = 0.0;
 83:         try {
 84:             for (int i = 1; i <= setsize; i += 2) {    // A density  of 50%: skip al odd positions on this dimension.
 85: 
 86:                 // Set each dimension only when it changes. 
 87:                 tup.getElement(0).setOrdinal(i);
 88:                 for (int j = 1; j <= setsize; ++j) {
 89:                     tup.getElement(1).setOrdinal(j);
 90:                     for (int k = 1; k <= setsize; ++k) {
 91:                         tup.getElement(2).setOrdinal(k);
 92:                         ++value;
 93: 
 94:                         m_LargePar.setValue(tup, value);
 95:                     }
 96:                 }
 97:             }
 98: 
 99:             m_Aimms.updateData();
100:         } catch (AimmsRuntimeException ex) {
101:             // setValue throws an AimmsRuntimeException if the elements of the tuple are not present in the index domain.
102:             logger.error("Catched a runtime exception: {}", ex.getMessage());
103:             m_Aimms.clearBuffers();
104: 
105:         } finally {
106: 
107:             stop();
108:             closeDataAndSession();
109:         }
110: 
111: 
112:     }
113: 
114:     /**
115:      * setValues: Efficient and convenient if the data to assign is dense. The
116:      * setLabels (for sets) and setValues (for data) methods do allow for dense
117:      * allocation of an identifier. The data will be added in the natural
118:      * ordering of the domains, thus combining ease of use with efficiency.
119:      */
120:     public void denseAssignLabels() {
121: 
122:         openSessionAndData();
123:         int setsize = m_Labels.length;
124:         logger.info("setsize: {} ", setsize);
125:         start("Assign string labels first to the set using setLabels and then use setValues on the IMultiDimData to assign the values to the parameter");
126: 
127: 
128:         m_SubSet.setLabels(m_Labels);
129: 
130:         // UpdateData is not neccesary here because after the setLabels method the set is immediately up-to-date.
131: 
132:         double[] values = new double[setsize * setsize * setsize];
133: 
134:         // Whether a loop like this is neccesary depends on the source of the values.
135:         double value = 0;
136:         int pos = 0;
137:         for (int i = 0; i < setsize; i += 2) {
138: 
139:             for (int j = 0; j < setsize; ++j) {
140:                 for (int k = 0; k < setsize; ++k) {
141:                     values[pos++] = ++value;
142:                 }
143:             }
144:             // Now insert a two dimensional slice with zero's (the default value), because this is a dense assign method but the data is not fully dense.
145:             for (int z = 0; z < setsize * setsize; ++z) {
146:                 values[pos++] = 0;
147:             }
148:         }
149: 
150:         m_LargePar.setValues(values);
151: 
152:         m_Aimms.updateData();
153: 
154:         stop();
155: 
156:         closeDataAndSession();
157:     }
158: 
159:     /**
160:      * Slices: Efficient if the data to be assigned is sparse and distributed in
161:      * a way slices can be defined. In this example multiple views are created
162:      * that are all restricted on the same level on a single element. This
163:      * reduces the dimension.
164:      */
165:     public void sliceAssignLabels() {
166: 
167:         openSessionAndData();
168:         int setsize = m_Labels.length;
169: 
170:         start("Assign string labels first to the set using setLabels and then use setValues on IDataView slices of the IMultiDimData to assign the values to the parameter");
171: 
172: 
173:         m_SubSet.setLabels(m_Labels);
174: 
175: 
176:         double[] values = new double[setsize * setsize];
177: 
178:         // Create a filter to slice the parameter.
179:         IFilter filter = m_LargePar.createFilter();
180: 
181:         double value = 0;
182:         for (int i = 0; i < setsize; i += 2) {
183:             // For each position of this dimension to which we will assign data, construct the filter to create a DataView. 
184:             // Notice the +=2, we only need views on the even positions.  
185:             filter.restrict(0, m_Labels[i]);
186:             IDataView slice = m_LargePar.openView(filter);
187: 
188:             int pos = 0;
189:             for (int j = 0; j < setsize; ++j) {
190:                 for (int k = 0; k < setsize; ++k) {
191:                     values[pos++] = ++value;
192:                 }
193:             }
194:             slice.setValues(values);
195:         }
196: 
197:         m_Aimms.updateData();
198: 
199:         stop();
200: 
201:         closeDataAndSession();
202:     }
203: 
204:     /**
205:      * Filtering by call domain: Efficient if the data is sparse and an
206:      * appropriate subset is available to filter with.
207:      */
208:     public void filteredAssignLabels() {
209: 
210:         openSessionAndData();
211:         int setsize = m_Labels.length;
212: 
213:         start("Assign string labels first to the set using setLabels and use setValues on an IDataView filtered by a subset to assign the values on the parameter");
214: 
215:         m_SubSet.setLabels(m_Labels);
216: 
217:         // Open a subset on the domainset to use as a call domain on the level to restrict.
218:         ISetData subsubset = m_Aimms.openSet("SubSubSet");
219:         IElement element = m_SubSet.createElement();
220: 
221:         for (int o = 1; o <= setsize; o += 2) {
222:             element.setOrdinal(o);
223:             subsubset.add(element);
224:         }
225:         m_Aimms.updateData();
226: 
227:         double[] values = new double[setsize / 2 * setsize * setsize];
228: 
229:         // Create a filter to slice the parameter.
230:         IFilter filter = m_LargePar.createFilter();
231:         filter.restrict(0, subsubset);
232:         IDataView view = m_LargePar.openView(filter);
233: 
234: 
235:         double value = 0;
236:         int pos = 0;
237:         for (int i = 0; i < setsize; i += 2) {
238:             for (int j = 0; j < setsize; ++j) {
239:                 for (int k = 0; k < setsize; ++k) {
240:                     values[pos++] = ++value;
241:                 }
242:             }
243:         }
244:         view.setValues(values);
245: 
246:         m_Aimms.updateData();
247: 
248:         stop();
249: 
250:         subsubset.close();
251:         closeDataAndSession();
252: 
253: 
254:     }
255: 
256:     // Helper functions
257:     private void openSessionAndData() {
258:         m_Aimms = null;
259:         m_Aimms = AIMMS.openSession(m_Location, m_Project);
260:         if (m_Aimms == null) {
261:             return;
262:         }
263:         m_SubSet = m_Aimms.openSet("LargeSubSet");
264:         m_LargePar = m_Aimms.openMultiDim("LargePar1");
265:     }
266: 
267:     private void closeDataAndSession() {
268:         m_LargePar.close();
269:         m_SubSet.close();
270:         m_Aimms.close();
271:     }
272: 
273:     private void start(String testDescription) {
274:         logger.info("Start Running {}...", testDescription);
275:         m_StartTime = new Date().getTime();
276:     }
277: 
278:     private void stop() {
279:         long stop = new Date().getTime();
280:         long dif = stop - m_StartTime;
281:         logger.info("This took {} milliseconds", dif);
282:         logger.info("");
283:     }
284: }