(uiop:define-package :st-buchberger/src/ideal (:mix :cl) (:mix-reexport :st-buchberger/src/groebner) (:export #:ideal #:make-ideal #:basis #:member-p)) (in-package #:st-buchberger/src/ideal) (defclass ideal () ((ring :initarg :ring :initform (error "You must specify a ring for the polynomial ideal.") :accessor ring) (generators :initarg :generators :initform (error "You must provide a set of generators for the ideal.") :accessor generators) (cached-basis))) (defun make-ideal (&rest generators) "Create a new ideal generated by the elements contained in the GENERATORS list." (when generators (let* ((g (first generators)) (base-ring (base-ring g))) (unless (every (lambda (x) (eq x base-ring)) (mapcar #'base-ring (rest generators))) (error "Every generator must belong to the same ring.")) (make-instance 'ideal :ring base-ring :generators (make-array (length generators) :element-type (class-of g) :initial-contents generators))))) (defmethod print-object ((ideal ideal) stream) (print-unreadable-object (ideal stream :type t) (format stream "~@{~S ~S~^ ~}" :ring (slot-value ideal 'ring) :generators (slot-value ideal 'generators)))) (defgeneric basis (ideal) (:documentation "Returns an array of generators for `ideal'.")) (defmethod basis ((ideal ideal)) (with-slots (cached-basis) ideal (setf cached-basis (reduced-groebner (generators ideal))) cached-basis)) (defgeneric member-p (element ideal)) (defmethod member-p ((element ring-element) (ideal ideal)) (with-slots (generators cached-basis) ideal (unless (and (slot-boundp ideal 'cached-basis) cached-basis) (setf cached-basis (basis ideal))) (ring-zero-p (ring-mod element cached-basis))))