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