Advertisement
Guest User

Untitled

a guest
Jan 16th, 2019
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.19 KB | None | 0 0
  1.  
  2. (*
  3. * SharpSolver - Progetto di Programmazione e Calcolo a.a. 2018-19
  4. * Impl.fsi: implementazioni degli studenti
  5. * (C) 2018 Alvise Spano' @ Universita' Ca' Foscari di Venezia
  6. *)
  7. module SharpSolver.Impl
  8.  
  9. open Absyn
  10. open Prelude
  11. open System
  12. open System.Runtime.Remoting.Metadata.W3cXsd2001
  13.  
  14.  
  15. let rationalize (x : float) : rational = //funzione che prende in input un float e restituisce la sua rappresentazione in tipo rational
  16. if float(int(x))=x then rational( int(x) ,1) // guardo se il numero non ha parte decimale e ritorno la parte intera / 1
  17. else let x_splt = x.ToString().Split ',' // spezza la parte intera e la parte decimale
  18. rational (int(""+x_splt.[0]+x_splt.[1]),int(10. ** float(x_splt.[1].Length))) //converto in stringa la parte intera e la concateno alla parte decimale(anch'essa convertita in intero). Compongo il denominatore elevando la base 10 al numero di cifre della parte decimale
  19. // e poi ritorno la coppia numeratore fratto denominatore del tipo rational
  20.  
  21. let monomial_degree (m : monomial) : int = // mi restituisce il grado di un singolo monomio
  22. match m with // confronto m (monomio)
  23. Monomial(x, y) -> y //siccome y mi rappresenta il grado del monomio, restituisco y alla chiamata di monomial_degree.
  24.  
  25. let monomial_negate (m : monomial) : monomial = //Nego il monomio.
  26. match m with // confronto m (monomio)
  27. Monomial(x ,y) -> Monomial(-x, y) // Siccome x rappresenta il coefficiente del monomio, restituisco -x alla chiamata di monomial_negate
  28. let rec polynomial_degree (p : polynomial) : int = //funzione ricorsiva che restituisce il grado di un polinomio sottoforma di intero.
  29. match p with
  30. |Polynomial([])->raise (NotImplementedException ()) // se il poliniomio dato in input è vuoto allora gestisco eccezione.
  31. |Polynomial([Monomial(x,y)])-> int(y) // se ho un singolo monomio allora il grado del polinomio sarà equivalente al grado del monomio: in questo caso y.
  32. |Polynomial(Monomial(x1,y1)::Monomial(x2,y2)::xs) -> if y2>y1 then polynomial_degree(Polynomial(Monomial(x2,y2)::xs)) else polynomial_degree(Polynomial(Monomial(x1,y1)::xs)) //Se ho un polinomio con due monomi come primi due elementi e una coda con altri monomi, allora confronto se il grado del secondo monomio è più grande del grado del primo monomio. Se sì allora assumo come massimo grado il secondo monomio e lo faccio diventare primo elemento concatenandolo alla coda. In caso contrario pongo il primo monomio come massimo grado il primo monomio e lo concateno alla coda facendolo restare il primo elemento. Così via fino alla fine del polinomio.
  33.  
  34. let polynomial_negate (p : polynomial) : polynomial = //nega un qualsiasi polinomio.
  35. let rec aux p= // utilizzo un'ausiliaria per comporre una lista di monomial_list
  36. match p with
  37. Polynomial([Monomial(x,y)])-> [monomial_negate (Monomial(x,y))] // caso base con un singolo monomio. nego il monomio usand la funzione monomial_negate precedente.
  38. |Polynomial(Monomial(x,y)::xs)->[monomial_negate (Monomial(x,y))]@(aux (Polynomial (xs))) // nel caso in cui ho un polinomio con un primo monomio come primo elemento e una coda con altri monomi nego il primo monomio e lo tratto come fosse una lista concatenando la coda.
  39. in Polynomial (aux p) // richiamando poi il tipo Polynomial nella funzione ausiliaria
  40.  
  41. let normalized_polynomial_degree (np : normalized_polynomial) : int = //funzione che restituisce il grado di un polinomio normalizzato sottoforma di intero.
  42. let norm_to_array np =
  43. match np with
  44. NormalizedPolynomial (np) -> np // estraggo tramite pattern matching il vettore di rational
  45. let d =Array.toList (norm_to_array(np)) // tramite la funzione di libreria Array.toList trasformo l'array di rational in una lista di rational
  46. let rec rational_to_monomiallist ls c = // funzione che trasforma una lista di rational in una monomial list
  47. match ls with
  48. [x]-> [Monomial(x,c)] // se ho solo un elemento della lista ritorno un elemento monomial con coppia di rational e grado c passato a parametro
  49. |x::xs-> (Monomial(x,c)) :: rational_to_monomiallist (xs) (c+1) //se ho una lista rational di più elementi converto tutta lista rational in una lista di monomi con coppia di rational e grado c passato a parametro
  50. let rec mono_to_poli l= // funzione che trasforma una lista di monomial list in un polinomio
  51. match l with
  52. [x]-> Polynomial([x]) // se la lista di monomi è di un solo elemento ritorno il polinomio con un solo elemento
  53. |x::xs ->Polynomial(x::xs) // se la lista di monomi ha più di un elemento ritorno il polinomio con una lista di più monomi
  54. in polynomial_degree (mono_to_poli(rational_to_monomiallist d 0)) // vado a richiamare la funzione polynomial_degree che ritorna il grado del polinomio passando a parametro il polinomio ottenuto tramite le due funzioni di appoggio
  55.  
  56. let normalize (p : polynomial) : normalized_polynomial = // funzione che permette di normalizzare un polinomio esempio: 3x+5x=0 -> 8x=0
  57. let rec polinomio_to_coppia lst= // trasformo il polinomio in una lista di coppie con rational e il grado del monomio
  58. match lst with
  59. Polynomial[Monomial(x,y)]-> [x,y]
  60. |Polynomial(Monomial(x,y)::xs)-> (x,y):: polinomio_to_coppia(Polynomial(xs))
  61. let array_poli = List.toArray(polinomio_to_coppia(p)) // trasformo la lista di coppie in un array
  62. let dim =polynomial_degree(p)+1 // dichiaro la dimensione del nuovo array che andrò ad inizializzare
  63. let arreo = Array.create(dim) (rational(0,1)) // creo il nuovo array di dimensione dim e inizializzo con rational a 0
  64. for i=0 to dim do // scorro il nuovo array dichiarato
  65. for j=0 to array_poli.Length-1 do // scorro l'array di coppie
  66. let (a,b) =array_poli.[j] // dichiaro una coppia e li assegno l'elemento in indice j
  67. if(b=i) then arreo.[i]<-arreo.[i]+a //se il grado è uguale alla posizione nel vettore creato inizialmente , sommo il valore già presente nella posizione i e sommo il coefficiente della coppia
  68.  
  69.  
  70. NormalizedPolynomial(arreo) // ritorno il vettore di rational
  71.  
  72.  
  73. let derive (p : polynomial) : polynomial = //calcolo la derivata del polinomio dato in input
  74. let rec aux p = // funzione ausiliaria che permette il calcolo della derivata
  75. match p with
  76. Polynomial([Monomial(x,y)]) -> ([Monomial(((rational y)*x), y-1)]) //se ho un polinomio che ha un singolo monomio applico la definizione di derviata. Moltiplico l'esponente (facendo un cast di rational su y) per il coefficente noto che è x. Dopodiché sottraggo di 1 l'esponente.
  77. |Polynomial(Monomial(x,y)::xs)-> ((Monomial(((rational y)*x), y-1))::(aux(Polynomial(xs)))) //se ho una lista di monomi quindi un polinomio formato da un primo elemento (un monomio) e una coda che può contenere una lista di monomi, applico la definizione di derivata al primo monomio della lista e poi concateno la coda in modo da scorrere tutta la lista e applicare la funzione a tutti i monomi.
  78. in Polynomial( aux p) //Ritorno la derivata del polinomio
  79.  
  80. let rec reduce (e : expr) : polynomial = //funzione che permette di distinguere un polinomio da una derivata
  81. match e with
  82. Poly e -> e // se ho un polinomio restituisco un polinomio
  83. |Derive e -> derive(reduce(e)) // se ho tipo derive applico la funzione derive in ricorsione e di conseguenza la funzione ritornerà il polinomio derivato
  84.  
  85. let solve0 (np : normalized_polynomial) : bool = // funzione che permette di risolvere le equazioni di grado 0
  86. let extract p =
  87. match np with
  88. NormalizedPolynomial(p) -> p // estraggo tramite pattern matching il vettore di rational
  89. let array = extract np // applico la funzione extract al polinomio normalizzato in input
  90. let a= array.[0] // accedo alla posizione 0 del vettore considerando 0 come il grado dell'equazione e quindi assegno ad a il coefficente del grado 0
  91. if(a=rational.Zero) then true else false //se il coefficiente è uguale a 0 ritorno true altrimenti false
  92.  
  93. let solve1 (np : normalized_polynomial) : rational = // funzione che permette di risolvere le equazioni di grado 1
  94. let extract p =
  95. match np with
  96. NormalizedPolynomial(p) -> p // estraggo tramite pattern matching il vettore di rational
  97. let array = extract np // applico la funzione extract al polinomio normalizzato in input
  98. let zero = array.[0] // accedo alla posizione 0 del vettore considerando 0 come il grado dell'equazione e quindi assegno ad a il coefficente del grado 0
  99. let one = array.[1] // accedo alla posizione 1 del vettore considerando 1 come il grado dell'equazione e quindi assegno ad a il coefficente del grado 1
  100. rational(((- zero.N)*(one.D)),((zero.D)*(one.N))) //moltiplico coefficiente di grado 1 e grado 0 ,alla fine ritorno l'unica soluzione dell'equazione di grado 1 di tipo rational
  101.  
  102.  
  103. let solve2 (np : normalized_polynomial) : (float * float option) option = // funzione che permette di risolvere le equazioni di grado 2
  104. let extract p =
  105. match np with
  106. NormalizedPolynomial(p) -> p // estraggo tramite pattern matching il vettore di rational
  107. let array = extract np // applico la funzione extract al polinomio normalizzato in input
  108. let zero = float(float(array.[0].N)/float(array.[0].D)) // accedo alla posizione 0 del vettore considerando 0 come il grado dell'equazione e quindi assegno a zero il coefficente del grado 0 , divido numeratore per il denominatore in modo da ottenere un numero float
  109. let one = float(float(array.[1].N)/float(array.[1].D)) // accedo alla posizione 1 del vettore considerando 1 come il grado dell'equazione e quindi assegno a one il coefficente del grado 1 , divido numeratore per il denominatore in modo da ottenere un numero float
  110. let two = float(float(array.[2].N)/float(array.[2].D)) // accedo alla posizione 2 del vettore considerando 2 come il grado dell'equazione e quindi assegno a two il coefficente del grado 2 , divido numeratore per il denominatore in modo da ottenere un numero float
  111. // il delta in quanto in matematica viene calcolato in questo modo delta = b^2 -4ac , ho deciso il procedimento in sottoprocedimenti sottostanti
  112. let delta1 = one*one // calcola il b^2 del delta
  113. let delta2 = 4.0 *zero*two // calcolo il 4ac del delta
  114. let delta = delta1 - delta2 // infine ottengono il delta effettuando b^2-4ac
  115. if(delta>0.) then // se il delta è maggiore di 0 andrò a ritornare 2 soluzioni
  116. let num1 = -one + sqrt(delta) // calcolo il -b+ la radice quadrata del delta (1a radice dell'equazione)
  117. let den1 = 2. *two //calcolo il denominatore 2*a
  118. let x1 = num1/ den1 // divido il numeratore con il denominatore quindi (-b + radice del delta) /2a ed ottengo la prima radice dell'equazione
  119. let num2 = -one - sqrt(delta) // calcolo il -b- la radice quadrata del delta (2a radice dell'equazione)
  120. let den2 = 2. *two //calcolo il denominatore 2*a
  121. let x2 = float(num2/den2) // divido il numeratore con il denominatore quindi (-b - radice del delta) /2a ed ottengo la seconda radice dell'equazione
  122. Some(x1,Some x2) //ritorno le due soluzioni
  123. elif(delta=0.) then // se il delta è uguale a 0 andrò a ritornare 2 soluzioni uguali.
  124. let num1 = -one // calcolo il -b+ la radice quadrata del delta (1a radice dell'equazione) , il delta è uguale a 0 e quindi non vado ne a sommare e ne a togliere la radice quadrata del delta
  125. let den1 = 2. *two //calcolo il denominatore 2*a
  126. let x1 = float(num1/ den1) // divido il numeratore con il denominatore (-b/2a) ed ottengo una radice dell'equazione
  127. Some(x1,None) // ritorno l'unica soluzione
  128. else None // se il delta è minore di 0 non ho soluzioni
  129.  
  130. let solve3 (np: normalized_polynomial) : (float * float option * float option) option =
  131. let extract p =
  132. match np with
  133. NormalizedPolynomial(p) -> p
  134. let array = extract np // applico la funzione extract al polinomio normalizzato in input
  135. let d = float(float(array.[0].N)/float(array.[0].D)) // accedo alla posizione 0 del vettore considerando 0 come il grado dell'equazione e quindi assegno a zero il coefficente del grado 0 , divido numeratore per il denominatore in modo da ottenere un numero float
  136. let c = float( float(array.[1].N)/ float(array.[1].D)) // accedo alla posizione 1 del vettore considerando 1 come il grado dell'equazione e quindi assegno a one il coefficente del grado 1 , divido numeratore per il denominatore in modo da ottenere un numero float
  137. let b = float( float(array.[2].N)/ float(array.[2].D)) // accedo alla posizione 2 del vettore considerando 2 come il grado dell'equazione e quindi assegno a two il coefficente del grado 2 , divido numeratore per il denominatore in modo da ottenere un numero float
  138. let a = float(float(array.[3].N)/ float(array.[3].D)) // accedo alla posizione 3 del vettore considerando 3 come grado dell'equazione e quindi assegno a three il coefficiente del grado 3, dividendo numeratore per denoinatore in modo da ottenere un numero float.
  139. let f = (((3.*c)/a)- ((b*b)/(a*a)))/3.
  140. let g = (((2.*(b*b*b))/(a*a*a)) - ((9.*b*c)/(a*a))+((27.*d)/a))/27.
  141. let h = ((g*g)/4.) + ((f*f*f)/27.0)
  142. if (f+g+h)=0. then // all roots are real and equal
  143. let x1 = Math.Pow(float(d/a),0.33333333333333333333333333333333)*(-1.)
  144. let x2 = Math.Pow(float(d/a),0.33333333333333333333333333333333)*(-1.)
  145. let x3 = Math.Pow(float(d/a),0.33333333333333333333333333333333)*(-1.)
  146. Some(x1,Some x2,Some x3)
  147. elif(h<=0.) then // all 3 roots are real
  148. let i = Math.Sqrt(((g*g)/4.) - h)
  149. let j = Math.Pow(i,0.33333333333333333333333333333333)
  150. let k = Math.Acos(-(g/(2.*i)))
  151. let l = j * -1.
  152. let m = Math.Cos(k/3.)
  153. let n = Math.Sqrt(3.) *Math.Sin(k/3.)
  154. let p = (b/(3.*a))* -1.
  155. let x1 = (2.*j)*Math.Cos(k/3.)-(b/(3.*a))
  156. let x2 = l * (m+n) + p
  157. let x3 = l * (m-n) + p
  158. Some(x1,Some x2,Some x3)
  159. elif(h>0.) then
  160. let r = (-1.*(g/2.0)) + Math.Sqrt(h)
  161. if r<0. then let s = Math.Pow(-r,0.33333333333333333333333333333333)
  162. let t = (-1.*(g/2.0)) - Math.Sqrt(h)
  163. if t<0. then let u = Math.Pow(-t,0.33333333333333333333333333333333)
  164. let x1 = (-s-u) - (b/(3.0*a))
  165. Some(x1,None,None)
  166. else
  167. let u = Math.Pow(t,0.33333333333333333333333333333333)
  168. let x1 = (-s+u) - (b/(3.0*a))
  169. Some(x1,None,None)
  170. else let s = Math.Pow(r,0.33333333333333333333333333333333)
  171. let t = (-1.*(g/2.0)) - Math.Sqrt(h)
  172. if t<0. then let u = Math.Pow(-t,0.33333333333333333333333333333333)
  173. let x1 = (s-u) - (b/(3.0*a))
  174. Some(x1,None,None)
  175. else
  176. let u = Math.Pow(t,0.33333333333333333333333333333333)
  177. let x1 = (s+u) - (b/(3.0*a))
  178. Some(x1,None,None)
  179.  
  180. else None
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement