Class: Silicium::Algebra::Differentiation

Inherits:
Object
  • Object
show all
Defined in:
lib/algebra_diff.rb

Overview

differentiating methods

Instance Method Summary collapse

Instance Method Details

#dif_2(str) ⇒ Object

dif_2(str)



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# 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) ⇒ Object

dif_cos(param) helps trigonometry_difs(str)



188
189
190
191
192
193
194
195
196
197
198
199
200
# 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) ⇒ Object

dif_sin(param) helps trigonometry_difs(str)



172
173
174
175
176
177
178
179
180
181
182
183
184
# 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) ⇒ Object

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



145
146
147
148
149
150
151
152
153
154
155
# 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) ⇒ Object

dif_x_a(a) goes for variable with a coefficient



119
120
121
122
123
124
125
126
127
128
# 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) ⇒ Object

dif_x_c© goes for constant



132
133
134
135
136
137
138
139
140
141
# 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) ⇒ Object

differentiate(str) differentiates given string



9
10
11
# File 'lib/algebra_diff.rb', line 9

def differentiate(str)
  dif_2(str)
end

#extract_variables(str, var_hash) ⇒ Object

extract_variables(str,var_hash)



88
89
90
91
92
93
94
95
96
97
98
# 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) ⇒ Object

fill_var_loop_inner(str,var_hash,ind_hash,ind)



49
50
51
52
53
54
55
56
57
# 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) ⇒ Object

fill_variables(str)



76
77
78
79
80
81
82
83
84
# 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) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
# 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) ⇒ Object

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



25
26
27
28
29
30
31
32
33
34
35
# 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) ⇒ Object



37
38
39
40
41
42
43
44
45
# 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) ⇒ Object

first_char_from(str, ch, ind)



15
16
17
18
19
20
21
# 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) ⇒ Object

fix_str_for_dif(str) gets rid of useless brackets



204
205
206
207
# 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) ⇒ Object

fix_trig_brackets(str) helps fix_str_for_dif(str) with trigonometry



211
212
213
214
215
216
217
218
219
220
221
# 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) ⇒ Object

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



225
226
227
228
229
230
231
232
233
# 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) ⇒ Object

run_difs(str) selects how to differentiate str



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 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) ⇒ Object

trigonometry_difs(str) goes for trigonometry



159
160
161
162
163
164
165
166
167
168
# 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