I'm learning functional programming using the SML language. While reading my study notes, I came across a question, that asks which kind of a function (tuppled or curried) performs faster.
I've looked at the video here, where the instructor says that this is a matter of language implementation and states (at 5:25) that SML/NJ performs faster with tuppled functions, but doesn't state why that is.
I think my instructor once said, that it's because the curried function creates more closures, but I think I didn't hear right.
Can someone, please, elaborate on this?
There's some more intermediate evaluation for curried functions. Let's say we wanted a function so sum three numbers. We consider the following two definitions:
fun sum (x,y,z) = x + y + z
Alternatively,
fun sum x y z = x + y + z
Consider the following rough evaluation trace on the first version:
:> sum(1,2,3)
1 + 2 + 3 (substitution using pattern matching on the contents of the tuple)
(1 + 2) + 3
3 + 3
6
On the other hand, with the curried version SML will construct some anonymous functions on the fly as it is evaluating the expression. This is because curried functions take advantage of the fact that anonymous functions can be returned as the results of other functions in order to capture the behavior of applying multiple arguments to a single function. Constructing the functions takes some constant amount of time.
:> sum 1 2 3
((sum 1) 2) 3
(((fn x => (fn y => (fn z => x + y + z))) 1) 2) 3
((fn y => (fn z => 1 + y + z)) 2) 3
(fn z => 1 + 2 + z) 3
1 + 2 + 3
(1 + 2) + 3
3 + 3
6
So there are some extra steps involved. It certainly should not cause performance issues in your program, however.
Related
I am having trouble understanding a method to implement a power function in SML using only iteration and multiplication.
my iteration is the following:
fun iterate 0 f x = x
| iterate n f x = iterate (n-1) f (f x);
while my multiplication is basically iterating recursively
fun multiply 0 f = 0
| multiply f x = iterate x (fn x => x + 1) (multiply x (f-1));
Power function would basically be an iteration of the multiplication of the same base but I don't know which value to decrement
power n f = iterate (mult n n) (fn x => x + 1) (power (n) (f-1))
which is definately wrong
power n f = iterate (mult n n) (fn x => x + 1) (power (n) (f-1))
So, when it comes to naming, I might definitely write power x y or power i j or power x n or some such, since x, y, i, j or n look like they're numbers or integers, whereas f looks like it's a function. So right off the bat you have:
fun power x y = iterate (...a...) (...b...) (...c...)
As for what goes into each of these three parts, ...a..., ...b... and ...c...:
a. The thing iterate calls n, which is the number of times to iterate.
b. The thing iterate calls f, which is the function to apply each time.
c. The thing iterate calls x, which is what is applied each time.
As elaborated on in How to make a multiplication function using just addition function and iterate function in SML, there is no point in making power call itself; the point of using iterate is to hand over recursion to this list-combinator rather than use explicit recursion (where power has a reference to itself somewhere in its definition).
I am new to Standard ML. I am trying to compute x squared i, where x is a real and i is an non-negative integer. The function should take two parameters, x and i
Here is what I have so far:
fun square x i = if (i<0) then 1 else x*i;
The error that I am getting is that the case object and rules do not agree
The unary negation operator in SML is not - as it is in most languages, but instead ~. That is likely what is causing the specific error you cite.
That said, there are some other issues with this code. L is not bound in the example you post for instance.
I think you may want your function to look more like
fun square (x : real) 0 = 1
| square x i = x * (square x (i - 1))
You'll want to recurse in order to compute the square.
Tell me please, How to forbid to open brackets? For example,
8 * (x + 1) It should be that way, not 8 * x + 8
Using evaluate = False doesn't help
The global evaluate flag will allow you to do this in the most natural manner:
>>> with evaluate(False):
... 8*(x+1)
...
8*(x + 1)
Otherwise, Mul(8, x + 1, evaluate=False) is a lower level way to do this. And conversion from a string (already in that form) is possible as
>>> S('8*(x+1)',evaluate=False)
8*(x + 1)
In general, SymPy will convert the expression to its internal format, which includes some minimal simplifications. For example, sqrt is represented internally as Pow(x,1/2). Also, some reordering of terms may happen.
In your specific case, you could try:
from sympy import factor
from sympy.abc import x, y
y = x + 1
g = 8 * y
g = factor(g)
print(g) # "8 * (x + 1)"
But, if for example you have g = y * y, SymPy will either represent it as a second power ((x + 1)**2), or expand it to x**2 + 2*x + 1.
PS: See also this answer by SymPy's maintainer for some possible workarounds. (It might complicate things later when you would like to evaluate or simplify this expression in other calculations.)
How about sympy.collect_const(sympy.S("8 * (x + 1)"), 8)?
In general you might be interested in some of these expression manipulations: https://docs.sympy.org/0.7.1/modules/simplify/simplify.html
I have two complicated mathematical expressions. How can I compare them, to find if they express the same using Maxima?
is(equal(e1, e2)). Note that "=" is identity (i.e. same expression), while "equal" is equivalence. E.g. is(equal(x*(x + 1), x^2 + x)) => true while is(x*(x + 1) = x^2 + x) => false. Note also that is(equal(e1, e2)) actually computes ratsimp(e1 - e2) and looks to see if the result is 0. Maxima cannot reduce all equivalent expressions to 0 so there are cases in which it will incorrectly return false.
I'm trying to implement a simple logistic regression example in Clojure using the Incanter data analysis library. I've successfully coded the Sigmoid and Cost functions, but Incanter's BFGS minimization function seems to be causing me quite some trouble.
(ns ml-clj.logistic
(:require [incanter.core :refer :all]
[incanter.optimize :refer :all]))
(defn sigmoid
"compute the inverse logit function, large positive numbers should be
close to 1, large negative numbers near 0,
z can be a scalar, vector or matrix.
sanity check: (sigmoid 0) should always evaluate to 0.5"
[z]
(div 1 (plus 1 (exp (minus z)))))
(defn cost-func
"computes the cost function (J) that will be minimized
inputs:params theta X matrix and Y vector"
[X y]
(let
[m (nrow X)
init-vals (matrix (take (ncol X) (repeat 0)))
z (mmult X init-vals)
h (sigmoid z)
f-half (mult (matrix (map - y)) (log (sigmoid (mmult X init-vals))))
s-half (mult (minus 1 y) (log (minus 1 (sigmoid (mmult X init-vals)))))
sub-tmp (minus f-half s-half)
J (mmult (/ 1 m) (reduce + sub-tmp))]
J))
When I try (minimize (cost-func X y) (matrix [0 0])) giving minimize a function and starting params the REPL throws an error.
ArityException Wrong number of args (2) passed to: optimize$minimize clojure.lang.AFn.throwArity (AFn.java:437)
I'm very confused as to what exactly the minimize function is expecting.
For reference, I rewrote it all in python, and all of the code runs as expected, using the same minimization algorithm.
import numpy as np
import scipy as sp
data = np.loadtxt('testSet.txt', delimiter='\t')
X = data[:,0:2]
y = data[:, 2]
def sigmoid(X):
return 1.0 / (1.0 + np.e**(-1.0 * X))
def compute_cost(theta, X, y):
m = y.shape[0]
h = sigmoid(X.dot(theta.T))
J = y.T.dot(np.log(h)) + (1.0 - y.T).dot(np.log(1.0 - h))
cost = (-1.0 / m) * J.sum()
return cost
def fit_logistic(X,y):
initial_thetas = np.zeros((len(X[0]), 1))
myargs = (X, y)
theta = sp.optimize.fmin_bfgs(compute_cost, x0=initial_thetas,
args=myargs)
return theta
outputting
Current function value: 0.594902
Iterations: 6
Function evaluations: 36
Gradient evaluations: 9
array([ 0.08108673, -0.12334958])
I don't understand why the Python code can run successfully, but my Clojure implementation fails. Any suggestions?
Update
rereading the docstring for minimize i've been trying to calculate the derivative of cost-func which throws a new error.
(def grad (gradient cost-func (matrix [0 0])))
(minimize cost-func (matrix [0 0]) (grad (matrix [0 0]) X))
ExceptionInfo throw+: {:exception "Matrices of different sizes cannot be differenced.", :asize [2 1], :bsize [1 2]} clatrix.core/- (core.clj:950)
using trans to convert the 1xn col matrix to a nx1 row matrix just yields the same error with opposite errors.
:asize [1 2], :bsize [2 1]}
I'm pretty lost here.
I can't say anything about your implementation, but incanter.optimize/minimize expects (at least) three parameters and you're giving it only two:
Arguments:
f -- Objective function. Takes a collection of values and returns a scalar
of the value of the function.
start -- Collection of initial guesses for the minimum
f-prime -- partial derivative of the objective function. Takes
a collection of values and returns a collection of partial
derivatives with respect to each variable. If this is not
provided it will be estimated using gradient-fn.
Unfortunately, I'm not able to tell you directly what to supply (for f-prime?) here but maybe someone else is. Btw, I think the ArityException Wrong number of args (2) passed to [...] is actually quite helpful here.
Edit: Actually, I think the docstring above is not correct, since the source code does not use gradient-fn to estimate f-prime. Maybe, you can use incanter.optimize/gradient to generate your own?
First, Your cost function should have a parameter for theta like your python implementation however your implementation has fixed as initial-value.
Second, if your cost-func is correct, then you can call optimize like this
(optimize (fn [theta] (cost-func theta X y)) [0 0 0])
Hope this can help you.