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

basis[R]

the ideal basis

Public Class Methods

new(sd, name) click to toggle source

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

__addXMLResource(link) click to toggle source

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
__constructJasObject() click to toggle source

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
get_ideal() click to toggle source

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
jas_hasDegreeList() click to toggle source

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
jas_hasLengthsList() click to toggle source

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
jas_hasVariables() click to toggle source

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
jas_homogenize(hv) click to toggle source

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