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