samples.rd

[index]

# Exercise

## Finite Sets

### Sets

    # sample-set01.rb

    require "algebra"
    #intersection
    p Set[0, 1, 2, 4] & Set[1, 3, 5] == Set[1]
    p Set[0, 1, 2, 4] & Set[7, 3, 5] == Set.phi

    #union
    p Set[0, 1, 2, 4] | Set[1, 3, 5] == Set[0, 1, 2, 3, 4, 5]

    #membership
    p Set[1, 3, 2].has? 1

    #inclusion
    p Set[3, 2, 1, 3] < Set[3, 1, 4, 2, 0]

### Maps

    # sample-map01.rb

    require "algebra"
    a = Map[0=>2, 1=>2, 2=>0]
    b = Map[0=>1, 1=>1, 2=>1]
    p a * b #=> {0=>2, 1=>2, 2=>2}

### Groups

    # sample-group01.rb

    require "algebra"
    e = Permutation[0, 1, 2, 3, 4]
    a = Permutation[1, 0, 3, 4, 2]
    b = Permutation[0, 2, 1, 3, 4]
    p a * b #=> [2, 0, 3, 4, 1]

    g = Group.new(e, a, b)
    g.complete!
    p g == PermutationGroup.symmetric(5) #=> true

## Calculation of polynomials

    # sample-polynomial01.rb

    require "algebra"
    P = Polynomial.create(Integer, "x")
    x = P.var
    p((x + 1)**100) #=> x^100 + 100x^99 + ... + 100x + 1

## Calculation of multi-variate polynomials

    # sample-polynomial02.rb

    require "algebra"
    P = Polynomial(Integer, "x", "y", "z")
    x, y, z = P.vars
    p((-x + y + z)*(x + y - z)*(x - y + z))
    #=> -z^3 + (y + x)z^2 + (y^2 - 2xy + x^2)z - y^3 + xy^2 + x^2y - x^3

## Calculation of multi-variate polynomials (2)

    # sample-m-polynomial01.rb

    require "algebra"
    P = MPolynomial(Integer)
    x, y, z, w = P.vars("xyz")
    p((-x + y + z)*(x + y - z)*(x - y + z))
    #=> -x^3 + x^2y + x^2z + xy^2 - 2xyz + xz^2 - y^3 + y^2z + yz^2 - z^3

## Remainder of the division of a polynomial by polynomials

    # sample-divmod01.rb

    require "algebra"
    P = MPolynomial(Rational)
    x, y, z = P.vars("xyz")
    f = x**2*y + x*y**2 + y*2 + z**3
    g = x*y-z**3
    h = y*2-6*z

    P.set_ord(:lex) # lex, grlex, grevlex
    puts "(#{f}).divmod([#{g}, #{h}]) =>", "#{f.divmod(g, h).inspect}"
    #=> (x^2y + xy^2 + 2y + z^3).divmod([xy - z^3, 2y - 6z]) =>
    #   [[x + y, 1/2z^3 + 1], xz^3 + 3z^4 + z^3 + 6z]
    #   = [[Quotient1,Quotient2], Remainder]

## Groebner basis

    # sample-groebner01.rb

    require "algebra"
    P = MPolynomial(Rational, "xyz")
    x, y, z = P.vars("xyz")
    f1 = x**2 + y**2 + z**2 -1
    f2 = x**2 + z**2 - y
    f3 = x - z
    p Groebner.basis([f1, f2, f3])
    #=> [x - z, y - 2z^2, z^4 + 1/2z^2 - 1/4]

## Prime field

    # sample-primefield01.rb

    require "algebra"
    Z13 = ResidueClassRing(Integer, 13)

    a, b, c, d, e, f, g = Z13
    p [e + c, e - c, e * c, e * 2001, 3 + c, 1/c, 1/c * c, d / d, b * 1 / b]
      #=> [6, 2, 8, 9, 5, 7, 1, 1, 1]
    p( (1...13).collect{|i|  Z13[i]**12} )
      #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

## Algebraic field

    # sample-algebraicfield01.rb

    require "algebra"

    Px = Polynomial(Rational, "x")
    x = Px.var
    F = ResidueClassRing(Px, x**2 + x + 1)
    x = F[x]
    p( (x + 1)**100 )
        #=> -x - 1
    p( (x-1)** 3 / (x**2 - 1) )
        #=> -3x - 3

    G = Polynomial(F, "y")
    y = G.var
    p( (x + y + 1)** 7 )
        #=> y^7 + (7x + 7)y^6 + 8xy^5 + 4y^4 + (4x + 4)y^3 + 5xy^2 + 7y + x + 1

    H = ResidueClassRing(G, y**5 + x*y + 1)
    y = H[y]
    p( 1/(x + y + 1)**7 )
      #=> (1798/3x + 1825/9)y^4 + (-74x + 5176/9)y^3 +
      #     (-6886/9x - 5917/9)y^2 + (1826/3x - 3101/9)y + 2146/9x + 4702/9

### This can be done as following

    # sample-algebraicfield02.rb

    require "algebra"

    F = AlgebraicExtensionField(Rational, "x") {|x| x**2 + x + 1}
    x = F.var
    p( (x + 1)**100 )
    p( (x-1)** 3 / (x**2 - 1) )

    H = AlgebraicExtensionField(F, "y") {|y| y**5 + x*y + 1}
    y = H.var
    p( 1/(x + y + 1)**7 )

## Quotient fields

### By taking the quotient field of the ring of Integer, rational numbers are obtained.

    # sample-quotientfield01.rb

    require "algebra"
    Q = LocalizedRing(Integer)
    a = Q.new(3, 5)
    b = Q.new(5, 3)
    p [a + b, a - b, a * b, a / b, a + 3, 1 + a]
      #=> [34/15, -16/15, 15/15, 9/25, 18/5, 8/5]

### Rational function field

    # sample-quotientfield02.rb

    require "algebra"

    F13 = ResidueClassRing(Integer, 13)

    P = Polynomial(F13, "x")
    Q = LocalizedRing(P)
    x = Q[P.var]
    p ( 1 / (x**2 - 1) - 1 / (x**3 - 1) )

    #This is equivalent to the following
    F = RationalFunctionField(F13, "x")
    x = F.var
    p ( 1 / (x**2 - 1) - 1 / (x**3 - 1) )

### Rational function field over the algebraic extension field

    # sample-quotientfield03.rb

    require "algebra"

    F13 = ResidueClassRing(Integer, 13)
    F = AlgebraicExtensionField(F13, "a") {|a| a**2 - 2}
    a = F.var
    RF = RationalFunctionField(F, "x")
    x = RF.var

    p( (a/4*x + RF.unity/2)/(x**2 + a*x + 1) +
      (-a/4*x + RF.unity/2)/(x**2 - a*x + 1) )
    #=> 1/(x**4 + 1)

### Algebraic function field

    # sample-quotientfield04.rb

    require "algebra"

    F13 = ResidueClassRing(Integer, 13)
    F = RationalFunctionField(F13, "x")
    x = F.var
    AF = AlgebraicExtensionField(F, "a") {|a| a**2 - 2*x}
    a = AF.var

    p( (a/4*x + AF.unity/2)/(x**2 + a*x + 1) +
      (-a/4*x + AF.unity/2)/(x**2 - a*x + 1) )
    #=> (-x^3 + x^2 + 1)/(x^4 + 11x^3 + 2x^2 + 1)

## Linear Algebra

### Linear equations

    # sample-gaussian-elimination01.rb

    require "algebra"
    M = MatrixAlgebra(Rational, 5, 4)
    a = M.matrix{|i, j| i + j}
    a.display #=>
      #[0, 1, 2, 3]
      #[1, 2, 3, 4]
      #[2, 3, 4, 5]
      #[3, 4, 5, 6]
      #[4, 5, 6, 7]
    a.kernel_basis.each do |v|
      puts "a * #{v} = #{a * v}"
      #=> a * [1, -2, 1, 0] = [0, 0, 0, 0, 0]
      #=> a * [2, -3, 0, 1] = [0, 0, 0, 0, 0]
    end

### Diagonalization of Square Matrix

    # sample-diagonalization01.rb

    require "algebra"
    class Rational# < Numeric
      def inspect; to_s; end
    end

    M = SquareMatrix(Rational, 3)
    a = M[[1,-1,-1], [-1,1,-1], [2,1,-1]]
    puts "A = "; a.display; puts
    #A =
    #  1,  -1,  -1
    # -1,   1,  -1
    #  2,   1,  -1

    extfield, roots, tmatrix, evalues, addelms, evectors, espaces,
          chpoly, facts = a.diagonalize

    puts "Charactoristic Poly.: #{chpoly} => #{facts}"
    #Charactoristic Poly.: t^3 - t^2 + t - 6 => (t - 2)(t^2 + t + 3)

    puts "Algebraic Numbers:"
    roots.each do |po, rs|
      puts "#{rs.join(', ')} : roots of #{po} == 0"
    end
    puts
    #Algebraic Numbers:
    #a, -a - 1 : roots of t^2 + t + 3 == 0

    puts "EigenSpaces: "
    evalues.uniq.each do |ev|
      puts "W_{#{ev}} = <#{espaces[ev].join(', ')}>"
    end
    puts
    #EigenSpaces:
    #W_{2} = <[4, -5, 1]>
    #W_{a} = <[1/3a + 1/3, 1/3a + 1/3, 1]>
    #W_{-a - 1} = <[-1/3a, -1/3a, 1]>

    puts "P = "; tmatrix.display; puts
    puts "P^-1 * A * P = "; (tmatrix.inverse * a * tmatrix).display; puts
    #P =
    #  4, 1/3a + 1/3, -1/3a
    # -5, 1/3a + 1/3, -1/3a
    #  1,   1,   1
    #
    #P^-1 * A * P =
    #  2,   0,   0
    #  0,   a,   0
    #  0,   0, -a - 1

### Elementary Divisors of Matrix

    # sample-elementary-divisor01.rb

    require "algebra"

    M = SquareMatrix(Rational, 4)
    a = M[
      [2, 0, 0, 0],
      [0, 2, 0, 0],
      [0, 0, 2, 0],
      [5, 0, 0, 2]
    ]
    P = Polynomial(Rational, "x")
    MP = SquareMatrix(P, 4)

    ac = a.char_matrix(MP)
    ac.display; puts #=>
    #x - 2,   0,   0,   0
    #  0, x - 2,   0,   0
    #  0,   0, x - 2,   0
    # -5,   0,   0, x - 2

    p ac.elementary_divisor #=> [1, x - 2, x - 2, x^2 - 4x + 4]

    require "matrix-algebra-triplet"
    at = ac.to_triplet.e_diagonalize

    at.body.display; puts #=>
    #  1,   0,   0,   0
    #  0, x - 2,   0,   0
    #  0,   0, x - 2,   0
    #  0,   0,   0, x^2 - 4x + 4

    at.left.display; puts #=>
    #  0,   0,   0, -1/5
    #  0,   1,   0,   0
    #  0,   0,   1,   0
    #  5,   0,   0, x - 2

    at.right.display; puts #=>
    #  1,   0,   0, 1/5x - 2/5
    #  0,   1,   0,   0
    #  0,   0,   1,   0
    #  0,   0,   0,   1

    p at.left * ac * at.right == at.body #=> true

### Jordan Canonical Form of Matrix

    # sample-jordan-form01.rb

    require "algebra"

    M4 = SquareMatrix(Rational, 4)
    m = M4[
        [-1, 1, 2, -1],
        [-5, 3, 4, -2],
        [3, -1, 0, 1],
        [5, -2, -2, 3]
    ]
    m.jordan_form.display; #=>
    #  2,   0,   0,   0
    #  0,   1,   1,   0
    #  0,   0,   1,   1
    #  0,   0,   0,   1
    puts

    #-----------------------------------
    m = M4[
      [3, 1, -1, 1],
      [-3, -1, 3, -1],
      [-2, -2, 0, 0],
      [0, 0, -4, 2]
    ]
    jf, pt, qt, field, modulus  = m.jordan_form_info
    p modulus #=> [a^2 + 4]
    jf.display; puts #=>
    #  2,   1,   0,   0
    #  0,   2,   0,   0
    #  0,   0,   a,   0
    #  0,   0,   0,  -a

    m = m.convert_to(jf.type)
    p jf == pt * m * qt #=> true

    #-----------------------------------
    m = M4[
        [-1, 1, 2, -1],
        [-5, 3, 4, -2],
        [3, -1, 0, 1],
        [5, -2, -2, 0]
    ]
    jf, pt, qt, field, modulus  = m.jordan_form_info
    p modulus #=> [a^3 + 3a - 1, b^2 + ab + a^2 + 3]
    jf.display; puts #=>
    #  2,   0,   0,   0
    #  0,   a,   0,   0
    #  0,   0,   b,   0
    #  0,   0,   0, -b - a

    m = m.convert_to(jf.type)
    p jf == pt * m * qt #=> true

### The proofs of the theorem of Cayley-Hamilton

    # sample-cayleyhamilton01.rb

    require "algebra"

    n = 4
    R = MPolynomial(Integer)
    MR = SquareMatrix(R, n)
    m = MR.matrix{|i, j| R.var("x#{i}#{j}") }
    Rx = Polynomial(R, "x")
    ch = m.char_polynomial(Rx)
    p ch.evaluate(m) #=> 0

## The expression of Groebner basis by original generators

    # sample-groebner02.rb

    require "algebra"

    P = MPolynomial(Rational)
    x, y, z = P.vars "xyz"
    f1 = x**2 + y**2 + z**2 -1
    f2 = x**2 + z**2 - y
    f3 = x - z

    coeff, basis = Groebner.basis_coeff([f1, f2, f3])
    basis.each_with_index do |b, i|
      p [coeff[i].inner_product([f1, f2, f3]), b]
      p coeff[i].inner_product([f1, f2, f3]) == b #=> true
    end

## The quotients and the remainder by arbitrary basis

    # sample-groebner03.rb

    require "algebra"
    F5 = ResidueClassRing(Integer, 2)
    F = AlgebraicExtensionField(F5, "a") {|a| a**3 + a + 1}
    a = F.var
    P = MPolynomial(F)

    x, y, z = P.vars("xyz")
    f1 = x + y**2 + z**2 - 1
    f2 = x**2 + z**2 - y * a
    f3 = x - z - a

    f = x**3 + y**3 + z**3
    q, r = f.divmod_s(f1, f2, f3)
    p f == q.inner_product([f1, f2, f3]) + r #=> true

## Factorization

### Factorization of Integer coefficient polynomial

    # sample-factorize01.rb

    require "algebra"

    P = Polynomial(Integer, "x")
    x = P.var
    f = 8*x**7 - 20*x**6 + 6*x**5 - 11*x**4 + 44*x**3 - 9*x**2 - 27
    p f.factorize #=> (2x - 3)^3(x^2 + x + 1)^2

### Factorization of Zp coefficient polynomial

    # sample-factorize02.rb

    require "algebra"

    Z7 = ResidueClassRing(Integer, 7)
    P = Polynomial(Z7, "x")
    x = P.var
    f = 8*x**7 - 20*x**6 + 6*x**5 - 11*x**4 + 44*x**3 - 9*x**2 - 27
    p f.factorize #=> (x + 5)^2(x + 3)^2(x + 2)^3

### Factorization of the algebraic extension of Rational polynomial

    # sample-factorize03.rb

    require "algebra"

    A = AlgebraicExtensionField(Rational, "a") {|a| a**2 + a + 1}
    a = A.var
    P = Polynomial(A, "x")
    x = P.var
    f = x**4 + (2*a + 1)*x**3 + 3*a*x**2 + (-3*a - 5)*x - a + 1
    p f.factorize #=> (x + a)^3(x - a + 1)

### Factorization of the algebraic extension of the algebraic extension of Rational

    # sample-factorize04.rb

    require "algebra"

    A = AlgebraicExtensionField(Rational, "a") {|a| a**2 - 2}
    B = AlgebraicExtensionField(A, "b"){|b| b**2 + 1}
    P = Polynomial(B, "x")
    x = P.var
    f = x**4 + 1
    p f.factorize
    #=> (x - 1/2ab - 1/2a)(x + 1/2ab - 1/2a)(x + 1/2ab + 1/2a)(x - 1/2ab + 1/2a)

### Factorization of x^4 + 10x^2 + 1

    # sample-factorize05.rb

    require "algebra"

    def show(f, mod = 0)
      if mod > 0
        zp = ResidueClassRing(Integer, mod)
        pzp = Polynomial(zp, f.variable)
        f = f.convert_to(pzp)
      end
      fact = f.factorize
      printf "mod %2d: %-15s  =>  %s\n", mod, f, fact
    end

    Px = Polynomial(Integer, "x")
    x = Px.var
    f = x**4 + 10*x**2 + 1
    #f = x**4 - 10*x**2 + 1
    show(f)
    Primes.new.each do |mod|
      break if mod > 100
      show(f, mod)
    end

    #mod  0: x^4 + 10x^2 + 1  =>  x^4 + 10x^2 + 1
    #mod  2: x^4 + 1          =>  (x + 1)^4
    #mod  3: x^4 + x^2 + 1    =>  (x + 2)^2(x + 1)^2
    #mod  5: x^4 + 1          =>  (x^2 + 3)(x^2 + 2)
    #mod  7: x^4 + 3x^2 + 1   =>  (x^2 + 4x + 6)(x^2 + 3x + 6)
    #mod 11: x^4 - x^2 + 1    =>  (x^2 + 5x + 1)(x^2 + 6x + 1)
    #mod 13: x^4 + 10x^2 + 1  =>  (x^2 - x + 12)(x^2 + x + 12)
    #mod 17: x^4 + 10x^2 + 1  =>  (x^2 + 3x + 1)(x^2 + 14x + 1)
    #mod 19: x^4 + 10x^2 + 1  =>  (x + 17)(x + 10)(x + 9)(x + 2)
    #mod 23: x^4 + 10x^2 + 1  =>  (x^2 + 6)(x^2 + 4)
    #mod 29: x^4 + 10x^2 + 1  =>  (x^2 + 21)(x^2 + 18)
    #mod 31: x^4 + 10x^2 + 1  =>  (x^2 + 22x + 30)(x^2 + 9x + 30)
    #mod 37: x^4 + 10x^2 + 1  =>  (x^2 + 32x + 36)(x^2 + 5x + 36)
    #mod 41: x^4 + 10x^2 + 1  =>  (x^2 + 19x + 1)(x^2 + 22x + 1)
    #mod 43: x^4 + 10x^2 + 1  =>  (x + 40)(x + 29)(x + 14)(x + 3)
    #mod 47: x^4 + 10x^2 + 1  =>  (x^2 + 32)(x^2 + 25)
    #mod 53: x^4 + 10x^2 + 1  =>  (x^2 + 41)(x^2 + 22)
    #mod 59: x^4 + 10x^2 + 1  =>  (x^2 + 13x + 1)(x^2 + 46x + 1)
    #mod 61: x^4 + 10x^2 + 1  =>  (x^2 + 54x + 60)(x^2 + 7x + 60)
    #mod 67: x^4 + 10x^2 + 1  =>  (x + 55)(x + 39)(x + 28)(x + 12)
    #mod 71: x^4 + 10x^2 + 1  =>  (x^2 + 43)(x^2 + 38)
    #mod 73: x^4 + 10x^2 + 1  =>  (x + 68)(x + 44)(x + 29)(x + 5)
    #mod 79: x^4 + 10x^2 + 1  =>  (x^2 + 64x + 78)(x^2 + 15x + 78)
    #mod 83: x^4 + 10x^2 + 1  =>  (x^2 + 18x + 1)(x^2 + 65x + 1)
    #mod 89: x^4 + 10x^2 + 1  =>  (x^2 + 9x + 1)(x^2 + 80x + 1)
    #mod 97: x^4 + 10x^2 + 1  =>  (x + 88)(x + 54)(x + 43)(x + 9)

### Factorization of Integer or Rational coefficient multi-variate polynomial

    # sample-m-factorize01.rb

    require "algebra"

    P = MPolynomial(Integer)
    x, y, z = P.vars("xyz")
    f = x**3 + y**3 + z**3 - 3*x*y*z
    p f.factorize #=> (x + y + z)(x^2 - xy - xz + y^2 - yz + z^2)

    PQ = MPolynomial(Rational)
    x, y, z = PQ.vars("xyz")
    f = x**3 + y**3/8 + z**3 - 3*x*y*z/2
    p f.factorize #=> (1/8)(2x + y + 2z)(4x^2 - 2xy - 4xz + y^2 - 2yz + 4z^2)

### Factorization of Zp coefficient multi-variate polynomial

    # sample-m-factorize02.rb

    require "algebra"

    Z7 = ResidueClassRing(Integer, 7)
    P = MPolynomial(Z7)
    x, y, z = P.vars("xyz")
    f = x**3 + y**3 + z**3 - 3*x*y*z
    p f.factorize #=> (x + 4y + 2z)(x + 2y + 4z)(x + y + z)

## Algebraic Equations

### Minimal Polynomial

    # sample-algebraic-equation01.rb

    require "algebra"

    PQ = MPolynomial(Rational)
    a, b, c = PQ.vars("abc")
    p AlgebraicEquation.minimal_polynomial(a + b + c, a**2-2, b**2-3, c**2-5)
    #=> x^8 - 40x^6 + 352x^4 - 960x^2 + 576

### Minimal Splitting Field

    # sample-splitting-field01.rb

    require "algebra"

    PQ = Polynomial(Rational, "x")
    x = PQ.var
    f = x**4 + 2
    p f #=> x^4 + 2
    field, modulus, facts = f.decompose
    p modulus #=> [a^4 + 2, b^2 + a^2]
    p facts #=> (x - a)(x + a)(x - b)(x + b)

    fp = Polynomial(field, "x")
    x = fp.var
    facts = Factors.new(facts.collect{|g, n| [g.evaluate(x), n]})
    p facts.pi == f.convert_to(fp) #=> true

### Galois Group of polynomials

    # sample-galois-group01.rb

    require "rational"
    require "polynomial"

    P = Algebra.Polynomial(Rational, "x")
    x = P.var

    (x**3 - 3*x + 1).galois_group.each do |g|
      p g
    end
    #=> [0, 1, 2]
    #   [1, 2, 0]
    #   [2, 0, 1]]

    (x**3 - x + 1).galois_group.each do |g|
      p g
    end
    #=> [0, 1, 2]
    #   [1, 0, 2]
    #   [2, 0, 1]
    #   [0, 2, 1]
    #   [1, 2, 0]
    #   [2, 1, 0]