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