Another Ruby conversion of a practical sheet from my course …​

1. Sets

Ruby has a set library, built-in.

1.1. Construction

Constructing a set is straightforward:

irb(main):001> set1 = Set[1,2,3,1]
=> Set[1, 2, 3]
irb(main):002> all = Set[%w{a b c d e}]
=> Set[["a", "b", "c", "d", "e"]]
irb(main):003> set2 = Set[2/5r, 4, 10.6]
=> Set[(2/5), 4, 10.6]

Notice that:

  • duplicate elements are dropped, and

  • rational fractions can be defined in Ruby using the "r" suffix.

For cardinality, use size (or length):

irb(main):004> set2.size
=> 3

Membership is tested using member? (or include?):

irb(main):005> set1.member? 4
=> false
irb(main):006> set2.member? 4
=> true

Equality is tested using ==:

irb(main):007> set1 == Set[1,2,3]
=> true
irb(main):008> set1 == Set[1,2,3,3,2,4]
=> false

1.2. Subsets

Two methods check subset relationships: subset? and proper_subset?

irb(main):009> s = Set[2]
=> Set[2]
irb(main):010> s.proper_subset? set1
=> true
irb(main):011> s.proper_subset? set2
=> false
irb(main):012> set1.proper_subset? set1
=> false
irb(main):013> set1.subset? set1
=> true
irb(main):014> s.subset? set1
=> true

1.3. Set operations

intersection and union methods cover the main two operations. difference can be used for set complement, against a known set.

irb(main):017> all = Set.new %w{a b c d e}
=> Set["a", "b", "c", "d", "e"]
irb(main):018> s1 = Set.new %w{a b c}
=> Set["a", "b", "c"]
irb(main):019> s2 = Set.new %w{c d}
=> Set["c", "d"]
irb(main):020> all.difference s1
=> Set["d", "e"]
irb(main):021> s1.intersection s2
=> Set["c"]
irb(main):022> s1.union s2
=> Set["a", "b", "c", "d"]

2. Functions

This section, in the original notes, is about plotting some functions using numpy; this is covered quite well by numo.

2.1. Trigonometric functions

We start with a list of 100 points between 0 and 3pi, which we can create using linspace from numo to define the range by the number of points:

irb(main):023> require 'numo/narray'
=> true
irb(main):025> theta = Numo::DFloat.linspace(0, 4*Math::PI, 100)
=>
Numo::DFloat#shape=[100]
[0, 0.0951998, 0.1904, 0.285599, 0.380799, 0.475999, 0.571199, 0.666398, ...]

We continue with numo operations to create lists of sin/cos values from these points:

irb(main):030> a = Numo::NMath.sin(theta)
=>
Numo::DFloat#shape=[100]
...
irb(main):031> b = Numo::NMath.cos(theta)
=>
Numo::DFloat#shape=[100]
...

The plotting part with gnuplot requires a little more setting up, and I do this in a separate file. The complete program is:

require 'numo/narray'
require 'gnuplot'

theta = Numo::DFloat.linspace(0, 4*Math::PI, 100)
a = Numo::NMath.sin(theta)
b = Numo::NMath.cos(theta)

Gnuplot.open do |gp|
  Gnuplot::Plot.new(gp) do |plot|
    plot.title "Trigonometric Functions"

    plot.data << Gnuplot::DataSet.new( [theta.to_a, a.to_a] ) do |ds|
      ds.title = "sin(x)"
      ds.with = "lines"
      ds.linewidth = 4
    end

    plot.data << Gnuplot::DataSet.new( [theta.to_a, b.to_a] ) do |ds|
      ds.title = "cos(x)"
      ds.with = "lines"
      ds.linewidth = 4
    end
  end
end

with the final display being:

gnuplot trig

2.2. Exponents and logarithms

numo provides exp, exp2 and exp10 taking the argument to powers of e, 2 and 10, respectively.

rb(main):035> x = Numo::DFloat.linspace(0, 10, 11)
=>
Numo::DFloat#shape=[11]
...
irb(main):036> x.to_a
=> [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
irb(main):037> Numo::NMath.exp(x)
=>
Numo::DFloat#shape=[11]
[1, 2.71828, 7.38906, 20.0855, 54.5982, 148.413, 403.429, 1096.63, 2980.96, ...]
irb(main):038> Numo::NMath.exp2(x)
=>
Numo::DFloat#shape=[11]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
irb(main):039> Numo::NMath.exp10(x)
=>
Numo::DFloat#shape=[11]
[1, 10, 100, 1000, 10000, 100000, 1e+06, 1e+07, 1e+08, 1e+09, 1e+10]

The following example graphs log, log2 and log10 from numo using gnuplot’s multiplot layout:

require 'numo/narray'
require 'gnuplot'
require 'gnuplot/multiplot'

x = Numo::DFloat.linspace(0.01, 10)
a = Numo::NMath.log(x)
b = Numo::NMath.log2(x)
c = Numo::NMath.log10(x)

Gnuplot.open do |gp|
  Gnuplot::Multiplot.new(gp, layout: [1,3]) do |mp|
    Gnuplot::Plot.new(mp) do |plot|
      plot.title "plot y1 = log(x)"
      plot.yrange "[-7:5]"
      plot.data << Gnuplot::DataSet.new( [x.to_a, a.to_a] ) do |ds|
        ds.with = "lines"
        ds.linewidth = 4
      end
    end

    Gnuplot::Plot.new(mp) do |plot|
      plot.title "plot y2 = log2(x)"
      plot.yrange "[-7:5]"
      plot.data << Gnuplot::DataSet.new( [x.to_a, b.to_a] ) do |ds|
        ds.with = "lines"
        ds.linewidth = 4
      end
    end

    Gnuplot::Plot.new(mp) do |plot|
      plot.title "plot y3 = log10(x)"
      plot.yrange "[-7:5]"
      plot.data << Gnuplot::DataSet.new( [x.to_a, c.to_a] ) do |ds|
        ds.with = "lines"
        ds.linewidth = 4
      end
    end
  end
end
gnuplot logs