class Silicium::Algebra::Differentiation

differentiating methods

Public Instance Methods

dif_2(str) click to toggle source

+dif_2(str)+

# File lib/algebra_diff.rb, line 237
def dif_2(str)
  var_hash = Hash.new
  str = fix_str_for_dif(str)
  str, var_hash = fill_variables(str)
  str.gsub!(/(?!^)-/,'+-')
  summ = str.split('+')
  if summ.length > 1
    arr = summ.map{|x|dif_2(extract_variables(x,var_hash))}.select{|x|x!="0"}
    if arr == []
      return "0"
    else
      res = arr.join('+')
      res.gsub!('+-','-')
      return res
    end
  end
  str = run_difs(str)
end
dif_cos(param) click to toggle source

+dif_cos(param)+ helps +trigonometry_difs(str)+

# File lib/algebra_diff.rb, line 188
def dif_cos(param)
  arg = dif_2(param)
  return case arg
         when '0'
           '0'
         when '1'
           "-1*Math::sin("+param+")"
         when /\A\d+\Z/
           "Math::sin("+param+")" + "*" + eval(arg + '*(-1)').to_s
         else
           "-1*Math::sin("+param+")" + "*(" + arg + ")"
         end
end
dif_sin(param) click to toggle source

+dif_sin(param)+ helps +trigonometry_difs(str)+

# File lib/algebra_diff.rb, line 172
def dif_sin(param)
  arg = dif_2(param)
  return case arg
         when '0'
           '0'
         when '1'
           "Math::cos("+param+")"
         when /\A\d+\Z/
           "Math::cos("+param+")" + "*" + arg
         else
           "Math::cos("+param+")" + "*(" + arg + ")"
         end
end
dif_x(a,b,c) click to toggle source

+dif_x(a,b,c)+ goes for a*x^b*c

# File lib/algebra_diff.rb, line 145
def dif_x(a,b,c)
  a, a_char = dif_x_a(a)
  c, c_char = dif_x_c(c)
  if b.nil? || b == "**1"
    return eval(a+a_char+"1"+c_char+c).to_s
  else
    new_b = '**' + (b[2,b.length - 2].to_i - 1).to_s
    new_b = '' if new_b == '**1'
    return eval(a+a_char+b[2,b.length - 2]+c_char+c).to_s + '*x' + new_b
  end
end
dif_x_a(a) click to toggle source

+dif_x_a(a)+ goes for variable with a coefficient

# File lib/algebra_diff.rb, line 119
def dif_x_a(a)
  if a.nil? || a == "1*" || a == ''
    a = ""
    a_char = ""
  else
    a_char = a[a.length - 1]
    a = eval(a[0,a.length-1]).to_s
  end
  [a, a_char]
end
dif_x_c(c) click to toggle source

+dif_x_c©+ goes for constant

# File lib/algebra_diff.rb, line 132
def dif_x_c(c)
  if c.nil? || c == "*1" || c == "/1" || c == ''
    c = ""
    c_char = ""
  else
    c_char = c[0]
    c = eval(c[1,c.length-1]).to_s
  end
  [c, c_char]
end
differentiate(str) click to toggle source

+differentiate(str)+ differentiates given string

# File lib/algebra_diff.rb, line 9
def differentiate(str)
  dif_2(str)
end
extract_variables(str,var_hash) click to toggle source

+extract_variables(str,var_hash)+

# File lib/algebra_diff.rb, line 88
def extract_variables(str,var_hash)
  ind = str[/#(\d+)/,1]
  return str if (ind.nil?)
  cur_var = var_hash[ind.to_i]
  while(true)
    str.sub!(/#(\d+)/,cur_var)
    ind = str[/#(\d+)/,1]
    return str if (ind.nil?)
    cur_var = var_hash[ind.to_i]
  end
end
fill_var_loop_inner(str,var_hash,ind_hash,ind) click to toggle source

+fill_var_loop_inner(str,var_hash,ind_hash,ind)+

# File lib/algebra_diff.rb, line 49
def fill_var_loop_inner(str,var_hash,ind_hash,ind)
  var_hash[ind_hash] = str[ind+1,ind2-ind-1]
  unless str[ind2+1] == '*' && str[ind2+2] == '*'
    str = str[0,ind2+1] + '**1' + str[ind2+1,str.length-1]
  end
  str = str[0,ind] + '#' + ind_hash.to_s + str[ind2+1,str.length-ind2-1]
  ind_hash += 1
  [str, var_hash, ind_hash, ind]
end
fill_variables(str) click to toggle source

+fill_variables(str)+

# File lib/algebra_diff.rb, line 76
def fill_variables(str)
  var_hash = {}
  ind_hash = 0
  if (str.include?('('))
    ind = first_char_from(str, '(', 0)
    str,var_hash = fill_variables_loop(str,var_hash,ind_hash,ind)
  end
  [str, var_hash]
end
fill_variables_loop(str,var_hash,ind_hash,ind) click to toggle source
# File lib/algebra_diff.rb, line 61
def fill_variables_loop(str,var_hash,ind_hash,ind)
  while ind != str.length
    ind2 = find_closing_bracket(str,ind + 1)
    if str[ind2].nil?
      puts 'bad string'
    else
      str, var_hash, ind_hash, ind = fill_var_loop_inner(str,var_hash, ind_hash, ind)
    end
    ind = first_char_from(str, '(', 0)
  end
  [str, var_hash]
end
find_closing_bracket(str, ind) click to toggle source

+find_closing_bracket(str,ind)+ finds the first closing bracket in str starting from given index

# File lib/algebra_diff.rb, line 25
def find_closing_bracket(str, ind)
  i = ind
  kind_of_a_stack = 0
  stop = true
  while i != str.length && stop
    stop, kind_of_a_stack = find_closing_bracket_inner(str,i,kind_of_a_stack)
    return i if !stop
    i+=1
  end
  i
end
find_closing_bracket_inner(str,i,kind_of_a_stack) click to toggle source
# File lib/algebra_diff.rb, line 37
def find_closing_bracket_inner(str,i,kind_of_a_stack)
  if str[i] == '('
    kind_of_a_stack += 1
  elsif str[i] ==  ')'
    kind_of_a_stack -= 1
    return [false, kind_of_a_stack] if kind_of_a_stack == 0
  end
  [true, kind_of_a_stack]
end
first_char_from(str, ch, ind) click to toggle source

+first_char_from(str, ch, ind)+

# File lib/algebra_diff.rb, line 15
def first_char_from(str, ch, ind)
  i = ind
  while(str[i] != ch) && (i != str.length)
    i+=1
  end
  i
end
fix_str_for_dif(str) click to toggle source

+fix_str_for_dif(str)+ gets rid of useless brackets

# File lib/algebra_diff.rb, line 204
def fix_str_for_dif(str)
  str = fix_trig_brackets(str)
  str = fix_useless_brackets(str)
end
fix_trig_brackets(str) click to toggle source

+fix_trig_brackets(str)+ helps +fix_str_for_dif(str)+ with trigonometry

# File lib/algebra_diff.rb, line 211
def fix_trig_brackets(str)
  reg = /(sin|cos)\((.+)\)/
  cur_el_1 = str[reg,1]
  cur_el_2 = str[reg,2]
  while(!cur_el_1.nil?)
    str.sub!(reg,cur_el_1+'<'+cur_el_2+'>')
    cur_el_1 = str[reg,1]
    cur_el_2 = str[reg,2]
  end
  str
end
fix_useless_brackets(str) click to toggle source

+fix_useless_brackets(str)+ helps +fix_str_for_dif(str)+ with extra brackets

# File lib/algebra_diff.rb, line 225
def fix_useless_brackets(str)
  reg1 = /\((-?\d+([*\/]\d)*|-?x([*\/]\d)*)\)/
  cur_el = str[reg1,1]
  while (!cur_el.nil?)
    str.sub!(reg1,cur_el)
    cur_el = str[reg1,1]
  end
  str
end
run_difs(str) click to toggle source

+run_difs(str)+ selects how to differentiate str

# File lib/algebra_diff.rb, line 102
def run_difs(str)
  return case str
         when /\A-?\d+\Z/
           '0'
         when /\A-?\d+\*\*+\d+\Z/
           '0'
         when /\A(-?(\d+[*\/])*)x(\*\*\d+)?([*\/]\d+)*\Z/
           dif_x($1,$3,$4)
         when /\AMath::(.+)/
           trigonometry_difs($1)
         else
           '0'
         end
end
trigonometry_difs(str) click to toggle source

+trigonometry_difs(str)+ goes for trigonometry

# File lib/algebra_diff.rb, line 159
def trigonometry_difs(str)
  return case str
         when /sin<(.+)>/
           dif_sin($1)
         when /cos<(.+)>/
           dif_cos($1)
         else
           '0'
         end
end