domain_checking.py
Go to the documentation of this file.
21
22from __future__ import print_function
23from gams import *
24import sys
25
27 return '''
28 Sets
29 i canning plants / seattle, san-diego /;
30
31 Alias (i,ii);'''
32
33if __name__ == "__main__":
34 if len(sys.argv) > 1:
35 ws = GamsWorkspace(system_directory = sys.argv[1])
36 else:
37 ws = GamsWorkspace()
38
39 # define some data by using Python data structures
40 plants = [ "Seattle", "San-Diego" ]
41 markets = [ "New-York", "Chicago", "Topeka" ]
42 capacity = { "Seattle": 350.0, "San-Diego": 600.0 }
43 demand = { "New-York": 325.0, "Chicago": 300.0, "Topeka": 275.0 }
44 distance = { ("Seattle", "New-York") : 2.5,
45 ("Seattle", "Chicago") : 1.7,
46 ("Seattle", "Topeka") : 1.8,
47 ("San-Diego", "New-York") : 2.5,
48 ("San-Diego", "Chicago") : 1.8,
49 ("San-Diego", "Topeka") : 1.4
50 }
51
52 # prepare a GamsDatabase with data from the Python data structures
53 db = ws.add_database()
54
55 # add two sets to the GamsDatabase
56 i = db.add_set("i", 1, "canning plants")
57 for p in plants:
58 i.add_record(p)
59
60 j = GamsSet(db, "j", 1, "markets")
61 for m in markets:
62 j.add_record(m)
63
64 # add a parameter with domain information
65 a = db.add_parameter_dc("a", [i], "capacity at plant")
66 for p in plants:
67 a.add_record(p).value = capacity[p]
68
69 # if we see a domain violation something went wrong
70 if not a.check_domains():
71 raise Exception("*** Unexpected domain violation in a")
72
73 # add a parameter with relaxed domain information
74 b = db.add_parameter_dc("b", ["j"], "demand at market j in cases")
75 for m in markets:
76 b.add_record(m).value = demand[m]
77
78 # if we see a domain violation something went wrong
79 if not b.check_domains():
80 raise Exception("*** Unexpected domain violation in b")
81
82 # add a 2-dim parameter with domain information
83 d = db.add_parameter_dc("d",[i,j], "distance in thousands of miles")
84 for k,v in iter(distance.items()):
85 d.add_record((k[0], k[1])).value = v
86
87 # if we see a domain violation something went wrong
88 if not d.check_domains():
89 raise Exception("*** Unexpected domain violation in d")
90
91 # if we see a domain violation in the database something went wrong
92 if not db.check_domains():
93 raise Exception("*** Unexpected domain violation in db")
94
95 # create some "wrong" entries
96 d.add_record(("Seattle", "aa")).value = 1
97 d.add_record(("bb", "Seattle")).value = 1
98 a.add_record("aa").value = 1
99 a.add_record("bb").value = 1
100 b.add_record("bb").value = 1
101 b.add_record("aa").value = 1
102
103 # now the GamsDatabase as well as the symbols a and d should have domain violations
104 if db.check_domains():
105 raise Exception("*** Domain violation for db not recognized")
106
107 if a.check_domains():
108 raise Exception("*** Domain violation for a not recognized")
109
110 if d.check_domains():
111 raise Exception("*** Domain violation for d not recognized")
112
113 # b in contrast was defined with realxed domain info only, therefore we should never see a domain violation
114 if not b.check_domains():
115 raise Exception("*** Unexpected domain violation in b")
116
117 # for a we should see 2 domain violations ("aa" and "bb")
118 dv_cnt = 0
119 print("Domain Violations of a:")
120 for sdv in a.get_symbol_dvs():
121 print(" > ", end="")
122 for vi in sdv.violation_idx:
123 print(vi, end=" ")
124 print("<> ", end="")
125 print(sdv.symbol_record.keys, end="")
126 print("<<")
127 dv_cnt +=1
128
129 if dv_cnt != 2:
130 raise Exception("*** Number of domain violations for a should be 2 but saw " + str(dvCnt))
131
132 # for d we should see 3 domain violations ("Seattle", *"aa"*; *"bb"*, *"Seattle"*)
133 dv_cnt = 0
134 print("Domain Violations of d:")
135 for sdv in d.get_symbol_dvs():
136 print(" > ", end="")
137 for vi in sdv.violation_idx:
138 print(vi, end=" ")
139 if vi:
140 dv_cnt +=1
141
142 print("<> ", end="")
143 print(sdv.symbol_record.keys, end="")
144 print("<<")
145
146 if dv_cnt != 3:
147 raise Exception("*** Number of domain violations for a should be 3 but saw ", str(dv_cnt))
148
149 # for db we should see 5 domain violations (all the ones from a and d)
150 dv_cnt = 0
151 print("Domain Violations of db:")
152 for ddv in db.get_database_dvs():
153 print(" > " + ddv.symbol.name + ": ")
154 for sdv in ddv.symbol_dvs:
155 print(" ", end="")
156 for vi in sdv.violation_idx:
157 print(vi, end=" ")
158 if vi:
159 dv_cnt += 1
160 print("<> ", end="")
161 print(sdv.symbol_record.keys, end="")
162 print ("<<")
163
164 if dv_cnt != 5:
165 raise Exception("*** Number of domain violations for db should be 5 but saw " + str(dv_cnt))
166
167 # now we limit the amount of violated records reported to a total of 3
168 dv_cnt = 0
169 print("Domain Violations of db:")
170 for ddv in db.get_database_dvs(3):
171 print(" > " + ddv.symbol.name + ": ")
172 for sdv in ddv.symbol_dvs:
173 print (" ", end="")
174 for vi in sdv.violation_idx:
175 print(vi, end=" ")
176 print("<> ", end="")
177 print(sdv.symbol_record.keys, end="")
178 print("<<")
179 dv_cnt += 1
180 if dv_cnt != 3:
181 raise Exception("*** Number of domain violations for db should be 3 but saw " + str(dv_cnt))
182
183 # now we limit the amount of violated records reported to 1 per symbol
184 dv_cnt = 0
185 print("Domain Violations of db:")
186 for ddv in db.get_database_dvs(0, 1):
187 print(" > " + ddv.symbol.name + ": ")
188 for sdv in ddv.symbol_dvs:
189 print(" ", end="")
190 for vi in sdv.violation_idx:
191 print(vi, end=" ")
192 print("<> ", end="")
193 print(sdv.symbol_record.keys, end="")
194 print("<<")
195 dv_cnt += 1
196
197 if dv_cnt != 2:
198 raise Exception("*** Number of domain violations for db should be 2 but saw " + str(dv_cnt))
199
200 # by default we should get an exception when exporting a GamsDatabase with domain violations
201 saw_exception = False
202 try:
203 db.export("test.gdx")
204 except:
205 saw_exception = True
206 db.suppress_auto_domain_checking = True
207 db.export("test.gdx")
208 if not saw_exception:
209 raise Exception("*** It should not be possible to export a GamsDatabase containing domain violations by default")
210
211 # read a parameter with domain info from gdx
212 db2 = ws.add_database_from_gdx("test.gdx")
213 d2 = db2.get_parameter("d")
214
215 # the domain of the parameter should be GamsSet i and GamsSet j
216 for item in d2.domains:
217 if isinstance(item, GamsSet):
218 if item.name == "i":
219 for uel in item:
220 if not uel.key(0) in plants:
221 raise Exception("*** Unexpected uel " + str(uel.key(0)) + " found in domain i")
222
223 elif item.name == "j":
224 for uel in item:
225 if not uel.key(0) in markets:
226 raise Exception("*** Unexpected uel " + str(uel.key(0)) + " found in domain j")
227
228 else:
229 raise Exception("*** Expected GamsSet i and j but found " + item.name)
230 else:
231 raise Exception("*** Expected GamsSet as domain but found relaxed domain " + item)
232
233 '''
234 This next section is acutally not about domain checking, but we
235 make sure that certain things are working as expected.
236 '''
237
238 # try reading an alias as set
239 j_alias = ws.add_job_from_string(get_data_text())
240 j_alias.run()
241 ii = j_alias.out_db.get_set("ii")
242 print("Elements of aliased Set:")
243 for item in ii:
244 print(" > " + item.key(0))
245
246 test_db = ws.add_database()
247 test_set = test_db.add_set("test", 1)
248
249 # Try adding empty UEL
250 test_set.add_record((""))
251 print("Elements of test Set after adding empty UEL:")
252 print(" > " + str(test_set.number_records))
253
254 # GAMS strips pending blanks while leading blanks are relevant
255 test_set.add_record(" a ").text = "a"
256 print("Record 'a' should be the same as 'a':")
257 print(" > " + test_set.find_record(" a").text)
258
259 # GAMS cannot handle UELs with more than 63 characters
260 # This should be OK ...
261 test_set.add_record("123456789012345678901234567890123456789012345678901234567890123 ").text = "OK"
262
263 # ... but not this
264 saw_exception = False
265 try:
266 test_set.add_record("1234567890123456789012345678901234567890123456789012345678901234").text = "not OK"
267 except:
268 saw_exception = True
269 if not saw_exception:
270 raise Exception("*** It should not be possible to add a record with more than 63 characters")
271
272 # GAMS cannot handle explanatory texts with more than 255 characters
273 test_db.add_set("textOK", 1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345")
274 saw_exception = False
275 try:
276 test_db.add_set("textNotOK", 1, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456")
277 except:
278 saw_exception = True
279 if not saw_exception:
280 raise Exception("*** It should not be possible to add an explanatory text with more than 255 characters")
281
282 test_set.add_record("OK").text = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"
283 saw_exception = False
284 try:
285 testSet.AddRecord("notOK").Text = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456"
286 except:
287 saw_exception = True
288 if not saw_exception:
289 raise Exception("*** It should not be possible to add an explanatory text with more than 255 characters")
290
291 # GAMS can handle UELs containing single and double quotes but not at the same time
292 test_set.add_record("quote'")
293 test_set.add_record("quote\"")
294 saw_exception = False
295 try:
296 test_set.add_record("quote'\"")
297 except:
298 saw_exception = True
299 if not saw_exception:
300 raise Exception("*** It should not be possible to add a record single AND double quote")
301 test_db.export("test.gdx")