class SD_Ideal
This class represents a SymbolicData
database object. The constructor takes a complete URI or a name SUBJ (the latter of which will be prefixed with the ‘ideal’ value from the sd.ini)
Any triple of the form (SUBJ, PRED, OBJ) will yield a field PRED* for the SD_Ideal
object with the value OBJ, where PRED* is the ending piece of PRED URI as defined by the function _uri_to_name()
A SPARQL
endpoint is needed. As a future improvement, it could be nice to directly parse an RDF in a convienient serialization.
Attributes
the ideal basis
Public Class Methods
sd is a SymbolicData
object, the name can be a complete URI or shortened name as defined by _uri_to_name(). The latter will be prefixed with the ‘ideal’ value from the sd.ini. Namespaces like “sd:Wu-90” are not (yet) supported.
Appart from retrieving the information from the SPARQL
endpoint, the resource data (XML files) is needed as well. While the SPARQL
endpoint can be substituted by another SPARQL
endpoint, the links to the resource files are ‘hard-coded’ into the RDF data. The possibility to use a (possibly ‘hand-filled’) cache will be included in the next update.
# File examples/sdjas.rb 258 def initialize(sd, name) 259 @dict = {} # mimic python 260 @_sd = sd 261 # quick test, if the given name already is an uri 262 if name[0,7] == 'http://' 263 @uri = name 264 else 265 @uri = @_sd._parser["symbolicdata"]["ideal"] + name 266 end 267 268 @dict["hasXMLResource"] = false 269 @dict["hasLengthsList"] = '' 270 @dict["hasDegreeList"] = '' 271 @dict["hasParameters"] = '' 272 273 @basis = [] 274 275 # we set up the query to get all predicate values 276 # of the URI/polynomial system/ideal 277 query = " 278 PREFIX sd: <#{@_sd.sd}> 279 SELECT ?p ?o WHERE { 280 <#{@uri}> ?p ?o 281 }" 282 #puts "query = " + query.to_s + "\n" 283 @_request = SPARQL.new(@_sd, query) 284 285 if @_request.json['results']['bindings'].size == 0 286 raise ArgumentError, "No data found for <#{@uri}>.\nMaybe the name was misspelled or the SPARQL endpoint is unavailable." 287 end 288 #puts "@_request.json = " + str(@_request.json) 289 290 # append the keys to the @dict. 291 for t in @_request.json['results']['bindings'] 292 uri = t['p']['value'] 293 obj = t['o']['value'] 294 @dict[_uri_to_name(uri)] = obj 295 end 296 #puts "@dict = " + str(@dict) 297 298 # Next we need a resource file with the actual expressions that are 299 # used to generate the ideal. 300 # 301 # There are four cases that need to be dealt with 302 # (1) the ideal is constructed direclty 303 # from an IntPS with related XML resource 304 # (2) the ideal is a flat variant of another 305 # ideal 306 # (3) the ideal is obtained by homogenizing 307 # another ideal 308 # (4) the ideal is obtained by parameterizing another 309 # ideal 310 # Please note: While it might seem that only one of (2) and (4) 311 # should be included, both are needed to map the actual history 312 # of how these ideals were obtained. 313 314 # case 1 315 if @dict.include?( 'relatedPolynomialSystem' ) 316 link = get_value_for_URI(@_sd, @dict["relatedPolynomialSystem"], @_sd.sd+'relatedXMLResource') 317 __addXMLResource(link) 318 @dict["hasXMLResource"] = true 319 #puts "relatedPolynomialSystem " + str(name) 320 end 321 322 # case 2 323 if @dict.include?( 'flatten' ) 324 parent_name = @dict["flatten"] 325 parent = SD_Ideal.new(@_sd, parent_name) 326 @variablesCSV = @dict["hasVariables"] 327 @variables = @variablesCSV.split(",").map{ |x| x.to_s.strip() } 328 @basis = parent.basis 329 #puts "flatten " + str(parent_name) + ", name = " + str(name) 330 end 331 332 # case 3 333 if @dict.include?( 'homogenize' ) 334 parent_name = @dict["homogenize"] 335 if @dict.include?( 'homogenizedWith' ) 336 hv = @dict["homogenizedWith"] 337 parent = SD_Ideal.new(@_sd, parent_name) 338 @variablesCSV = parent.variablesCSV + "," + hv 339 @variables = parent.variables 340 @variables.append(hv) 341 @basis = parent.jas_homogenize(hv) 342 #puts "homogenize " + str(parent_name) + ", name = " + str(name) 343 end 344 end 345 346 # case 4 347 if @dict.include?( 'parameterize' ) 348 parent_name = @dict["parameterize"] 349 parent = SD_Ideal.new(@_sd, parent_name) 350 @variablesCSV = @dict["hasVariables"] 351 @variables = @variablesCSV.split(",").map{ |x| x.to_s.strip() } 352 @basis = parent.basis 353 #puts "parameterize " + str(parent_name) + ", name = " + str(name) 354 end 355 356 # now we got the variables, the parameters and 357 # the strings/expressions for the polynomials 358 __constructJasObject() 359 end
Public Instance Methods
Fill internal objects.
# File examples/sdjas.rb 373 def __addXMLResource(link) 374 #xml = requests.get(link).text 375 #puts "link_xml = " + str(link) 376 #url = link[0:23] 377 path = link[23,link.length-23] # hack for lost domain 378 #puts "url = " + str(url) 379 #url = @_sd.url[:-5] 380 url = URI("http://" + @_sd.sdhost.to_s) 381 #puts "url = " + str(url) 382 383 xml = nil 384 Net::HTTP.start( url.host, url.port ) do |conn| 385 #puts "path = " + str(path) 386 url.path = path 387 #puts "path = " + str(url.request_uri) 388 #conn.request("GET", path ); 389 req = Net::HTTP::Get.new(url.request_uri) 390 response = conn.request( req ); 391 if not response.is_a?(Net::HTTPSuccess) 392 puts "response = " + response.to_s + "\n" 393 raise RuntimeError, "HTTP GET #{url} not successful" 394 end 395 #puts "head = " + response.code.to_s + " " + response.msg + "\n" 396 xml = response.body(); 397 end 398 puts _uri_to_name(link).to_s + " = " + xml.to_s 399 400 #xmlTree = parseString(xml) 401 xmlTree = REXML::Document.new(xml) 402 #puts "xmlTree = " + str(xmlTree) 403 404 # Code snipped borrowed from Albert Heinle 405 if xmlTree.elements.to_a("*/vars").empty? # Check, if vars are there 406 raise ArgumentError, "The given XMLString does not contain variables for the IntPS System" 407 end 408 if xmlTree.elements.to_a("*/basis").empty? # Check, if we have a basis 409 raise ArgumentError, "The given XMLString does not contain a basis for the IntPS System" 410 end 411 # -------------------- Input Check finished -------------------- 412 # From here, we can assume that the input is given correct 413 @variablesCSV = xmlTree.elements.to_a("*/vars")[0].text 414 #puts "@variablesCSV = " + @variablesCSV.to_s 415 @variables = @variablesCSV.split(",").map{|x| x.to_s.strip() } 416 #polynomials = xmlTree.elements.to_a("*/basis")[0] 417 @basis = xmlTree.elements.to_a("*/basis/poly").map{ |poly| poly.text.to_s.strip() } 418 #puts "@basis = " + @basis.to_s 419 end
Construct the ideal as a Jas object.
# File examples/sdjas.rb 424 def __constructJasObject() 425 #require "jas" 426 # set up the polynomial ring (Jas syntax) 427 if @dict.include?('hasParameters') and @dict['hasParameters'] != '' 428 #K = 'K.<%s> = PolynomialRing(ZZ)' % @hasParameters 429 #R = K + '; R.<%s> = PolynomialRing(K)' % @hasVariables 430 kk = PolyRing.new(ZZ(), @dict['hasParameters'].to_s ) 431 rr = PolyRing.new(kk, @dict['hasVariables'].to_s ) 432 gens = '%s,%s' % [@dict['hasParameters'], @dict['hasVariables']] 433 else 434 #R = 'R.<%s> = PolynomialRing(ZZ)' % (@hasVariables) 435 rr = PolyRing.new(ZZ(), @dict['hasVariables'].to_s ) 436 gens = '%s' % @dict['hasVariables'] 437 end 438 # execute remaining JAS semantic constructs 439 #exec(preparse(R)) 440 ##rr = rr + "; " + gens + " = rr.gens();" 441 #puts "rr = " + str(rr) 442 rv = "one," + gens + " = rr.gens();" 443 #puts "rv = " + str(rv) 444 myb = binding 445 #pr = eval(rr.to_s, myb) 446 pr = eval(rv.to_s, myb) # safe here since rr did evaluate 447 @jasRing = rr; 448 #puts "pr = " + str(pr) 449 450 # avoid XSS: check if polynomials are clean 451 vs = GenPolynomialTokenizer.expressionVariables(gens.to_s) 452 vs = vs.sort 453 #puts "vs = " + str(vs) 454 vsb = [] 455 @basis.each{ |s| vsb += GenPolynomialTokenizer.expressionVariables(s.to_s) } 456 vsb = vsb.sort.uniq 457 #puts "vsb = " + str(vsb) 458 if vs != vsb 459 raise SyntaxError, "invalid variables: expected " + vs.to_s + ", got " + vsb.to_s 460 end 461 # construct polynomials in the constructed ring from 462 # the polynomial expressions 463 @jasBasis = [] 464 for ps in @basis 465 #puts "ps = " + str(ps) 466 ps = ps.to_s 467 ps = ps.gsub('^', '**') 468 #exec(preparse("symbdata_ideal = %s" % ps)) 469 pol = eval("symbdata_poly = %s" % ps, myb) 470 #puts "pol = " + str(pol) 471 @jasBasis.push(pol) 472 end 473 #puts "jasBasis = " + str(@jasBasis) 474 end
Return the ideal as a Jas object.
# File examples/sdjas.rb 365 def get_ideal() 366 #return ideal(@sageBasis) 367 return @jasRing.ideal("",@jasBasis) 368 end
This is the implementation of the predicate “sd:hasDegreeList”. The degree list is the sorted list of the degree of the generator of the ideal.
Along with the output, there will also be generated a field FROM_JAS_hasDegreeList which can be used to later access the data without recalculating. The main reason for this is that the SymbolicData
properties are converted into field, not getter functions. So to have some symmetry, the Jas calculations will end up in fields as well.
# File examples/sdjas.rb 514 def jas_hasDegreeList() 515 begin 516 ll = @jasBasis.map{|x| x.degree() }.sort 517 @FROM_JAS_hasDegreeList = ll.map{|x| x.to_s}.join(",") 518 rescue 519 @FROM_JAS_hasDegreeList = '' 520 end 521 return @FROM_JAS_hasDegreeList 522 end
This is the implementation of the predicate “sd:hasLengthsList”. The lengths lists is the sorted list of the number of monomials of the generator of the ideal.
Along with the output, there will also be generated a field FROM_JAS_hasLengthsList which can be used to later access the data without recalculating. The main reason for this is that the SymbolicData
properties are converted into field, not getter functions. So to have some symmetry, the Jas calculations will end up in fields as well.
# File examples/sdjas.rb 492 def jas_hasLengthsList() 493 begin 494 ll = @jasBasis.map{|x| x.size() }.sort 495 @FROM_JAS_hasLengthsList = ll.map{|x| x.to_s}.join(",") 496 rescue 497 @FROM_JAS_hasLengthsList = '' 498 end 499 return @FROM_JAS_hasLengthsList 500 end
This is the implementation of the predicate “sd:hasVariables”. This is actually not needed.
# File examples/sdjas.rb 528 def jas_hasVariables() 529 #K = [] 530 #DL = map(lambda m : K.extend(map(lambda l : str(l), m.variables())), @sageBasis) 531 kk = @jasRing.ring.vars 532 #return sorted(list(set(kk))).join(",") 533 return kk.sort().uniq().join(",") 534 end
Homogenize a basis, which here means actually nothing more than homogenizing every element of the basis.
# File examples/sdjas.rb 540 def jas_homogenize(hv) 541 homBasis = @jasBasis.map{ |x| x.homogenize(hv) } 542 return homBasis 543 end