class Algebra::MPolynomial

Public Class Methods

[](*x) click to toggle source
# File lib/algebra/m-polynomial.rb, line 191
def self.[](*x)
  new(Hash[*x])
end
const(x) click to toggle source
# File lib/algebra/m-polynomial.rb, line 177
def self.const(x)
  new({Algebra::MIndex::Unity => x})
end
create(ground, *vars) click to toggle source
Calls superclass method
# File lib/algebra/m-polynomial.rb, line 119
def self.create(ground, *vars)
  klass = super(ground)
  klass.sysvar(:order, nil)
  klass.sysvar(:v_order, nil)
  klass.set_ord(:lex)
  klass.sysvar(:variables, vars)
  klass.sysvar(:display_type, :norm)
  klass
end
euclidian?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 195
def self.euclidian?
  ground.euclidian? && variables.size <= 1
end
get_ord() click to toggle source
# File lib/algebra/m-polynomial.rb, line 297
def self.get_ord
  order
end
get_v_ord() click to toggle source
# File lib/algebra/m-polynomial.rb, line 305
def self.get_v_ord
  v_order
end
indeterminate(obj) click to toggle source
# File lib/algebra/m-polynomial.rb, line 145
  def self.indeterminate(obj)
    ind = if i = variables.index(obj)
            [0] * i + [1]
#           Algebra::MIndex.monomial(i)
          else
            variables.push obj
#           [0] * (variables.size-1) + [1]
            Algebra::MIndex.monomial(variables.size-1)
          end
    monomial(ind)
  end
method_cash_clear(*m) click to toggle source
# File lib/algebra/m-polynomial.rb, line 342
  def self.method_cash_clear(*m)
#    $stderr.puts "method_cash_clear is given no parameter" if m.empty?
    m.each do |x|
      x.method_cash_clear
    end
  end
monomial(ind = [1], c = ground.unity) click to toggle source
# File lib/algebra/m-polynomial.rb, line 169
def self.monomial(ind = [1], c = ground.unity)
   new({Algebra::MIndex[*ind] => c})
end
mvar(*array) click to toggle source
# File lib/algebra/m-polynomial.rb, line 161
def self.mvar(*array)
  if array.empty?
    variables.collect{|var| indeterminate(var) }
  else
    array.collect{|var| indeterminate(var)}
  end
end
new(ha = {}) click to toggle source
# File lib/algebra/m-polynomial.rb, line 114
def initialize(ha = {})
  @bone = ha
  method_cash_clear
end
ord() click to toggle source
# File lib/algebra/m-polynomial.rb, line 301
def self.ord
  get_ord
end
ord=(ord) click to toggle source
# File lib/algebra/m-polynomial.rb, line 293
def self.ord=(ord)
  self.set_ord(ord, nil)
end
regulate(x) click to toggle source
# File lib/algebra/m-polynomial.rb, line 181
def self.regulate(x)
  if x.is_a? self
    x
  elsif y = ground.regulate(x)
    const(y)
  else
    nil
  end
end
set_ord(ord = nil, v_ord = nil) click to toggle source
# File lib/algebra/m-polynomial.rb, line 267
  def self.set_ord(ord = nil, v_ord = nil)
#    @@order = MonomialOrder.new(ord, v_ord)
    if ord.is_a? String
      ord = ord.intern
    elsif ord.is_a?(Symbol) || ord.nil?
    else
      raise "#{ord} must be String or Symbol"
    end
    if v_ord.is_a? String
      v_ord = v_ord.intern
    elsif v_ord.is_a?(Symbol) || v_ord.nil?
    else
      raise "#{v_ord} must be String or Symbol"
    end

    if ord.nil?
      ord = get_ord
    end
#    self.order = MonomialOrder.new(ord, v_ord) #o
    self.order = ord if ord #n
    self.v_order = v_ord if v_ord #n

    MIndex.set_ord(ord) if ord #n
    MIndex.set_v_ord(v_ord) if v_ord #n
  end
to_ary() click to toggle source
# File lib/algebra/m-polynomial.rb, line 141
def self.to_ary
  [self, *vars]
end
ufd?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 199
def self.ufd?
  euclidian? || ground.field?
end
unity() click to toggle source
# File lib/algebra/m-polynomial.rb, line 263
def self.unity; const(ground.unity); end
var(obj) click to toggle source
# File lib/algebra/m-polynomial.rb, line 157
def self.var(obj)
  indeterminate(obj)
end
vars(*vs) click to toggle source
# File lib/algebra/m-polynomial.rb, line 132
def self.vars(*vs)
  if vs.size > 0
    vs = vs[0].scan(/[a-zA-Z]_?\d*/) if vs.size == 1 && vs[0].is_a?(String)
    vs.collect{|var| indeterminate(var)}
  else
    variables.collect{|var| indeterminate(var) }
  end
end
with_ord(ord = nil, v_ord = nil, methods = []) { || ... } click to toggle source
# File lib/algebra/m-polynomial.rb, line 322
def self.with_ord(ord = nil, v_ord = nil, methods = [])
  method_cash_clear(*methods)
  o_ord, o_v_ord = get_ord, get_v_ord
  ord = o_ord unless ord
  result = nil

  if v_ord
    MIndex.set_v_ord(ord, v_ord)
    MIndex.import_module(MIndex.get_module(ord || self.order, v_ord)) do
      result = yield
    end
    MIndex.set_v_ord(o_ord, o_v_ord)
  else
    MIndex.import_module(MIndex.get_module(ord || self.order)) do
      result = yield
    end
  end
  result
end
with_ord_old(ord = nil, v_ord = nil, methods = []) { || ... } click to toggle source
# File lib/algebra/m-polynomial.rb, line 309
def self.with_ord_old(ord = nil, v_ord = nil, methods = [])
  method_cash_clear(*methods)
  o_ord, o_v_ord = get_ord, get_v_ord
  result = nil
  begin
    set_ord(ord, v_ord)
    result = yield
  ensure
    set_ord(o_ord, o_v_ord)
  end
  result
end
zero() click to toggle source
# File lib/algebra/m-polynomial.rb, line 261
def self.zero; new; end

Public Instance Methods

%(others) click to toggle source
# File lib/algebra/m-polynomial.rb, line 539
def %(others)
  divmod(*others).last
end
*(other) click to toggle source
Calls superclass method Algebra::AlgebraBase#*
# File lib/algebra/m-polynomial.rb, line 450
  def *(other)
    super{ |other|
      a = zero
      each do |m0, c0|
        other.each do |m1, c1|
          a[m0 + m1] +=  c0 * c1
        end
      end
#      a.compact!
      a
    }
  end
+(other) click to toggle source
Calls superclass method Algebra::AlgebraBase#+
# File lib/algebra/m-polynomial.rb, line 419
  def +(other)
    super{ |other|
      a = zero
      each do |m, c|
        a[m] = c + other[m]
      end
      other.each do |m, c|
        if !include? m
          a[m] = self[m] + c
#         a[m] = c + self[m]
        end
      end
      a
    }
  end
-(other) click to toggle source
Calls superclass method Algebra::AlgebraBase#-
# File lib/algebra/m-polynomial.rb, line 435
def -(other)
  super{ |other|
    a = zero
    each do |m, c|
      a[m] = c - other[m]
    end
    other.each do |m, c|
      if !include? m
        a[m] = self[m] - c
      end
    end
    a
  }
end
/(other) click to toggle source
Calls superclass method Algebra::AlgebraBase#/
# File lib/algebra/m-polynomial.rb, line 463
  def /(other) # other asume to be scalar
    #    if (o = regulate(other))
    super{ |o|
      if o.constant?
#       self * (ground.unity / o.constant_coeff)
        project{|c, ind|
          c/o.constant_coeff
        }
      else
        a, r = divmod(other)
        if r.zero?
          a.first
        else
          raise "#{other} not divides #{self}"
        end
      end
    }
#    else
#      raise "other(#{o}, #{o.class}) must be monomial"
#    end
  end
<=>(other) click to toggle source
# File lib/algebra/m-polynomial.rb, line 407
  def <=>(other)
    if o = regulate(other)
      # THIS IS RATHER VAGUE
      #      lm.ind <=> o.lm.ind
#      self.class.order.cmp(lm.ind, o.lm.ind) #o
      lm.ind <=> o.lm.ind #n
    else
       x , y = other.coerce(self)
      x <=> y
    end
  end
==(other) click to toggle source
Calls superclass method Algebra::AlgebraBase#==
# File lib/algebra/m-polynomial.rb, line 393
def ==(other)
  super{ |other|
    each do |m, c|
      return false unless c == other[m]
    end
    other.each do |m, c|
      if !include? m
        return false unless c.zero?
      end
    end
    true
  }
end
[](ind) click to toggle source
# File lib/algebra/m-polynomial.rb, line 209
def [](ind)
  @bone[ind] || 0
end
[]=(ind, c) click to toggle source
# File lib/algebra/m-polynomial.rb, line 213
def []=(ind, c)
  @bone[ind] = c
end
annihilate_away_from(n, e = 0) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 211
def annihilate_away_from(n, e = 0)
  # n = 0, e = 2
  # x*y*z + x*y**2*z + x*y*z + y*z + z**3 #=> x*y*z + y*z + z**3
  project(self.class) do |c, ind|
    ind.totdeg - ind[n] > e ? ground.zero : c
  end
end
call(*ary)
Alias for: evaluate
coeffs_at(an) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 251
def coeffs_at(an)
  ss = (0..deg_at(an)).collect { zero }
  each do |ind, c|
    next if c.zero?
    md = ind.annihilate(an)
    ss[ind[an]] += monomial(md, c)
  end
  ss
end
collect_away_from(n, ps) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 271
def collect_away_from(n, ps)
  # 2*x*y*z + x**2*y*z + x*y #=> [y*z=>(2*x + x**2), y=>x]
  h_alpha = {}
  each do |ind, c|
    next if c.zero?
    i = ind[n]
    ind0 = ind.annihilate(n)
    v = ps.var
    h_alpha[ind0] = h_alpha[ind0] ? h_alpha[ind0] + c * v**i : c * v**i
  end
  h_alpha
end
compact!() click to toggle source
# File lib/algebra/m-polynomial.rb, line 353
def compact!
  a = {}
  each do |m, c|
    a[m.compact] = c unless c.zero?
  end
  @bone = a
  self
end
constant?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 231
def constant?
  each do |m, c|
    if m.totdeg > 0 && !c.zero?
      return false
    end
  end
  true
end
constant_coeff() click to toggle source
# File lib/algebra/m-polynomial.rb, line 244
  def constant_coeff
    # we assume {[]=>2, [0]=>3} is not appeared.
    # it must be reduced to {[]=>6}.
    @bone[Algebra::MIndex::Unity]
#    k = ground.unity
#    @bone.each do |ind, c|
#      unless c.zero?
#       k *= c if ind.totdeg == 0
#      end
#    end
#    k
  end
convert_to(ring) click to toggle source
# File lib/algebra/m-polynomial.rb, line 645
def convert_to(ring)
  project(ring){|c, ind| c}
end
deg() click to toggle source
# File lib/algebra/m-polynomial.rb, line 391
def deg; multideg; end
deg_at(an) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 219
def deg_at(an)
  if zero?
    -1
  else
    max = 0
    each do |ind, c|
      unless c.zero?
        t = ind[an]
        max = t if t > max
      end
    end
    max
  end
end
derivate(v) click to toggle source
# File lib/algebra/m-polynomial.rb, line 616
def derivate(v)
  if an = self.class.variables.index(v) || vars.index(v)
    derivate_at(an)
  else
    raise "#{var} is not a variable"
  end
end
derivate_at(an) click to toggle source
# File lib/algebra/m-polynomial.rb, line 624
def derivate_at(an)
  ary = vars
  project0 {|c, ind|
    if ind[an] < 1
      zero
    else
      ind0 = ind - Algebra::MIndex.monomial(an)
      index_eval(self.class, ary, ind0) * ind[an] * c
    end
  }
end
divmod(*f) click to toggle source
# File lib/algebra/m-polynomial.rb, line 485
def divmod(*f)
  g = clone # not dup
  f_lts = f.collect{|x| x.lt}
  a = (0...f.size).collect{zero}
  r = zero
  until g.zero?
    flag = false
    f_lts.each_with_index do |f_lt, i|
      g_lt = g.lt
      if f_lt.divide? g_lt
        d = g_lt / f_lt
        if d == 0 then exit; end
        a[i] += d
        g = g.rt - (d * f[i]).rt
        g.compact!
        flag = true
        break
      end
    end
    unless flag
      r += g.lt
      g = g.rt #g.rt!
      g.compact!
    end
  end
  [a, r]
end
divmod_variant(*f) click to toggle source
# File lib/algebra/m-polynomial.rb, line 513
def divmod_variant(*f)
  g = clone # not dup
  f_lts = f.collect{|x| x.lt}
  a = (0...f.size).collect{zero}
  r = zero
  until g.zero?
    flag = false
    f_lts.each_with_index do |f_lt, i|
      g_lt = g.lt
      if f_lt.divide? g_lt
        d = g_lt / f_lt
        a[i] += d
        g = g.rt - (d * f[i]).rt
        g.compact!
        flag = true
        g.zero? ? break : redo
      end
    end
    unless flag
      r += g.lt
      g = g.rt #g.rt!
    end
  end
  [a, r]
end
each(&b) click to toggle source
# File lib/algebra/m-polynomial.rb, line 203
def each(&b); @bone.each(&b); end
evaluate(*ary) click to toggle source
# File lib/algebra/m-polynomial.rb, line 598
  def evaluate(*ary)
    project(ground, ary){|c, ind| c}
#    project(self.class, ary){|c, ind| c}
  end
Also aliased as: call
factorize() click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 188
def factorize
  return Algebra::Factors.new([[zero, 1]]) if zero?
  fact = if ground <= Integer
           factorize_int
         elsif defined?(Rational) && ground <= Rational ||
               defined?(LocalizedRing) && ground <= LocalizedRing
           factorize_rational
         elsif defined?(ResidueClassRing) && ground <= ResidueClassRing && ground.ground <= Integer
           factorize_modp
         else
           factorize_alg
         end
  fact.normalize!
end
gcd(other) click to toggle source
# File lib/algebra/annihilate.rb, line 25
def gcd(other)
  (self * other).divmod(lcm(other)).first.first
end
gcd_all(*a) click to toggle source
# File lib/algebra/annihilate.rb, line 29
def gcd_all(*a)
  t = self
  a.each do |x|
    break if t.constant?
    t = t.gcd(x)
  end
  t
end
include?(k) click to toggle source
# File lib/algebra/m-polynomial.rb, line 257
def include?(k)
  @bone.include?(k)
end
index_eval(ring, ary, ind) click to toggle source
# File lib/algebra/m-polynomial.rb, line 572
def index_eval(ring, ary, ind)
  e = ring.unity
  ind.each_with_index do |n, i|
    e *= ary[i]**n if n > 0
  end
  e
end
indice_of_constant() click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 234
def indice_of_constant
  (0...vars.size).find_all { |an| deg_at(an) <= 0 }
end
inspect()
Alias for: to_s
keys() click to toggle source
# File lib/algebra/m-polynomial.rb, line 205
def keys; @bone.keys; end
lc() click to toggle source
# File lib/algebra/m-polynomial.rb, line 548
def lc
  @lc ||= self[multideg]
end
lc_at(an) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 238
def lc_at(an)
  d = deg_at(an)
  s = zero
  each do |ind, c|
    next if c.zero?
    if ind[an] == d
      md = ind.annihilate(an)
      s += monomial(md, c)
    end
  end
  s
end
lcm(other) click to toggle source
# File lib/algebra/annihilate.rb, line 6
def lcm(other)
  vars0 = vars
  mp = MPolynomial.create(ground)
  mp.vars('t', *vars)
  t = mp.vars.first
  mpvars = mp.vars
  f = project0(mp) do |c, ind|
    c * index_eval(mp, mpvars, [0] + ind.to_a)
  end
  g = other.project0(mp) do |c, ind|
    c * index_eval(mp, mpvars, [0] + ind.to_a)
  end
  gb = Groebner.basis([t * f, (1 - t) * g])
  lcm0 = gb.last
  lcm0.project0(self.class) do |c, ind|
    c * index_eval(self.class, vars0, ind.empty? ? [] : ind[1..-1])
  end
end
lm() click to toggle source
# File lib/algebra/m-polynomial.rb, line 552
def lm
  #@lm ||= monomial(multideg).extend(Monomial)
  monomial(multideg).extend(Monomial)
end
lt() click to toggle source
# File lib/algebra/m-polynomial.rb, line 557
def lt
  md = multideg
  @lt ||= monomial(md, self[md]).extend(Monomial)
end
map_to(ring = self.class, ary = ring.vars)
Alias for: project0
method_cash_clear() click to toggle source
# File lib/algebra/m-polynomial.rb, line 349
def method_cash_clear
  @lc = @lm = @lt = @rt = @multideg = nil
end
monomial(ind = [1], c = ground.unity) click to toggle source
# File lib/algebra/m-polynomial.rb, line 173
def monomial(ind = [1], c = ground.unity)
  self.class.monomial(ind, c)
end
monomial?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 217
def monomial?
  flag = false
  each do |m, c|
    unless c.zero?
      if flag
        return false
      else
        flag = true
      end
    end
  end
  flag
end
move_const(pb, coef = ground.unity) click to toggle source
# File lib/algebra/m-polynomial.rb, line 636
def move_const(pb, coef = ground.unity)
  vs = self.class.vars.dup
  a = []
  vs.each_with_index do |x, i|
    a << x + pb[i]*coef
  end
  evaluate(*a)
end
multideg() click to toggle source
# File lib/algebra/m-polynomial.rb, line 362
  def multideg
    if @multideg
      @multideg
    else
      d = Algebra::MIndex::Unity
      each do |m, c|
#       d = m if !c.zero? && m > d
#       d = m if !c.zero? && self.class.order.cmp(m, d) > 0 #o
        d = m if !c.zero? && (m <=> d) > 0 #n
      end
      @multideg = d
    end
  end
need_paren_in_coeff?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 649
def need_paren_in_coeff?
  if constant?
    c = constant_coeff
    if c.respond_to?(:need_paren_in_coeff?)
      c.need_paren_in_coeff?
    elsif c.is_a?(Numeric)
      false
    else
      true
    end
  elsif !monomial?
    true
  else
    false
  end
end
project(ring = self.class, ary = ring.vars) { |c, ind| ... } click to toggle source
# File lib/algebra/m-polynomial.rb, line 590
def project(ring = self.class, ary = ring.vars)
  e = ring.zero
  each do |ind, c|
    e += index_eval(ring, ary, ind) * yield(c, ind)
  end
  e
end
project0(ring = self.class, ary = ring.vars) { |c, ind| ... } click to toggle source
# File lib/algebra/m-polynomial.rb, line 580
def project0(ring = self.class, ary = ring.vars)
  e = ring.zero
  each do |ind, c|
    e += yield(c, ind)
  end
  e
end
Also aliased as: map_to
reduce2onevar(pring, n) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 203
def reduce2onevar(pring, n)
  evar = []
  self.class.vars.each_with_index do |_v, i|
    evar.push i == n ? pring.var : pring.zero
  end
  project(pring, evar) { |c, _ind| c }
end
rt() click to toggle source
# File lib/algebra/m-polynomial.rb, line 562
def rt
  @rt ||= self - lt
end
rt!() click to toggle source
# File lib/algebra/m-polynomial.rb, line 566
def rt! # deepy destructive, do NOT use
  @bone.delete(multideg)
  method_cash_clear
  self
end
sub(var, value) click to toggle source
# File lib/algebra/m-polynomial.rb, line 603
def sub(var, value)
  vs = self.class.vars
  if i = vs.index(var)
    vs = vs.dup
    vs[i] = value
    evaluate(*vs)
  else
    raise "#{var} is not a variable"
  end
end
to_s() click to toggle source
# File lib/algebra/m-polynomial.rb, line 666
  def to_s
    case self.class.display_type
    when :code
      pr, po =  "*",  "**"
    when :tex
      pr, po =  "",  "}^"
    else
      pr, po =  "",  "^"
    end
    a = []
#    (k = keys).sort!
#    k = keys.sort{|x, y| self.class.order.cmp(x, y)} #o
    k = keys.sort{|x, y| x <=> y} #n
    k.each do |m| c = self[m]
      next if c.zero?
      s =  if m.unity?
            c.to_s
           else
             case c
             when Numeric
               c = c == 1 ? "" : c == -1 ? "-" : c.to_s
             when self.class
               c = "(#{c})"
             else
               c = if c == 1
                     ""
                   elsif c == -1
                     "-"
                   elsif c.respond_to?(:need_paren_in_coeff?)
                     if c.need_paren_in_coeff?
                       "(#{c})"
                     else
                       c.to_s
                     end
                   elsif c.is_a?(Numeric)
                     c.to_s
                   else
                     "(#{c})"
                   end
             end

             ms = m.to_s(variables, pr, po)
             c.empty? ? ms : c + pr + ms
           end
      a.unshift s
    end
    a.unshift "0" if a.empty?
    a.join(" + ").gsub(/\+ -/, "- ")
  end
Also aliased as: inspect
totdeg() click to toggle source
# File lib/algebra/m-polynomial.rb, line 376
def totdeg
  if zero?
    -1
  else
    max = 0
    each do |ind, c|
      unless c.zero?
        t = ind.totdeg
        max = t if t > max
      end
    end
    max
  end
end
totdeg_away_from(n) click to toggle source
# File lib/algebra/m-polynomial-factor.rb, line 261
def totdeg_away_from(n)
  max = 0
  each do |ind, c|
    next if c.zero?
    m = ind.totdeg - ind[n]
    max = m if m > max
  end
  max
end
unit?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 240
def unit?
  constant? && lc.unit?
end
values() click to toggle source
# File lib/algebra/m-polynomial.rb, line 207
def values; @bone.values; end
variables() click to toggle source
# File lib/algebra/m-polynomial.rb, line 129
def variables; self.class.variables; end
vars() click to toggle source
# File lib/algebra/m-polynomial.rb, line 130
def vars; self.class.vars; end
zero?() click to toggle source
# File lib/algebra/m-polynomial.rb, line 265
def zero?; !find{|m, c| !c.zero?}; end