Find maximum of a function - optimization

I need to find a maximum of the function:
a1^x1 * const1 + a2^x2 * const2 +....+ ak^xk * constk = qaulity
where xk>0 and xk is integer. ak is constant.
constraint:
a1^x1 * const1*func(x1) + a2^x2 * const2*func(x2) +....+ ak^xk * constk*func(xk) < Budget
Where func is a discrete function:
func(x)
{
switch(x)
{
case 1: return 423;
case 2: return 544;
...
etc
}
}
k may be big(over 1000). x less then 100.
What is the best method?

There are techniques like nelder-mead optimization (which I believe GSL implements), but most techniques assume some sort of special structure (i.e. convexity or continuity). Depending on the values of the function, there may not exist a unique optimum or even an optimum that a normal downhill method can find.

Related

sum of setof in prolog

I have this predicate to get the sum of the length of all borders of a country. I could solve it with findall but I have to use setof. My facts look like this:
borders(sweden,finland,586).
borders(norway,sweden,1619).
My code
circumference(C, Country) :-
findall(X, ( borders(Country, _, X) ; borders(_, Country, X)), Kms),
sum_list(Kms, C).
You cannot find the sum using bagof directly, all you can do is make a list and then sum that list (but you knew that already). In SWI-Prolog there is library(aggregate) that does the bagging and the summing for you. With the facts you have, you would write:
?- aggregate(sum(X), Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Circumference).
Circumference = 2205.
If you instead must obey the whims of your instructor and type "bagof" yourself, or if you are not allowed to use a modern, open source, comprehensive Prolog implementation, you can use the same approach with bagof and manually build the list before summing it:
?- bagof(X, Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Borders).
Borders = [1619, 586].
For reasons that are lost in the mists of time the funny thing with the Var^Goal that you see in both aggregate and bagof is called "existentially qualifying the variables in Goal". You might also read that "^ prevents binding Var in Goal". I cannot explain what this really means.
I ended up using this:
circumference(Z, Country) :- setof(X, Q^(borders(Q,Country,X);borders(Country,Q,X)),Border),
sum_list(Border,Z).
% Adds the numbers in a list.
sum_list([], 0).
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.

Factorial in Google BigQuery

I need to compute the factorial of a variable in Google BigQuery - is there a function for this? I cannot find one in the documentation here:
https://cloud.google.com/bigquery/query-reference#arithmeticoperators
My proposed solution at this point is to compute the factorial for numbers 1 through 100 and upload that as a table and join with that table. If you have something better, please advise.
As context may reveal a best solution, the factorial is used in the context of computing a Poisson probability of a random variable (number of events in a window of time). See the first equation here: https://en.wikipedia.org/wiki/Poisson_distribution
Try below. Quick & dirty example
select number, factorial
FROM js(
// input table
(select number from
(select 4 as number),
(select 6 as number),
(select 12 as number)
),
// input columns
number,
// output schema
"[{name: 'number', type: 'integer'},
{name: 'factorial', type: 'integer'}]",
// function
"function(r, emit){
function fact(num)
{
if(num<0)
return 0;
var fact=1;
for(var i=num;i>1;i--)
fact*=i;
return fact;
}
var factorial = fact(r.number)
emit({number: r.number, factorial: factorial});
}"
)
If the direct approach works for the values you need the Poisson distribution calculated on, then cool. If you reach the point where it blows up or gives you inaccurate results, then read on for numerical analysis fun times.
In general you'll get better range and numerical stability if you do the arithmetic on the logarithms, and then exp() as the final operation.
You want: c^k / k! exp(-c).
Compute its log, ln( c^k / k! exp(-c) ),
i.e. k ln(x) - ln(k!) - c
Take exp() of that.
Well but how do we get ln(k!) without computing k!? There's a function called the gamma function, whose practical point here is that its logarithm gammaln() can be approximated directly, and ln(k!) = gammaln(k+1).
There is a Javascript gammaln() in Phil Mainwaring's answer here, which I have not tested, but assuming it works it should fit into a UDF for you.
Extending Mikhail's answer to be general and correct for computing the factorial for all number 1 to n, where n < 500, the following solution holds and can be computed efficiently:
select number, factorial
FROM js(
// input table
(
SELECT
ROW_NUMBER() OVER() AS number,
some_thing_from_the_table
FROM
[any table with at least LIMIT many entries]
LIMIT
100 #Change this to any number to compute factorials from 1 to this number
),
// input columns
number,
// output schema
"[{name: 'number', type: 'integer'},
{name: 'factorial', type: 'float'}]",
// function
"function(r, emit){
function fact(num)
{
if(num<0)
return 0;
var fact=1;
for(var i=num;i>1;i--)
fact*=i;
return fact;
}
#Use toExponential and parseFloat to handle large integers in both Javascript and BigQuery
emit({number: r.number, factorial: parseFloat(fact(r.number).toExponential())});
}"
)
You can get up to 27! using SQL UDF. Above that value NUMERIC type gets overflow error.
CREATE OR REPLACE FUNCTION factorial(integer_expr INT64) AS ( (
SELECT
ARRAY<numeric>[
1,
1,
2,
6,
24,
120,
720,
5040,
40320,
362880,
3628800,
39916800,
479001600,
6227020800,
87178291200,
1307674368000,
20922789888000,
355687428096000,
6402373705728000,
121645100408832000,
2432902008176640000,
51090942171709440000.,
1124000727777607680000.,
25852016738884976640000.,
620448401733239439360000.,
15511210043330985984000000.,
403291461126605635584000000.,
10888869450418352160768000000.][
OFFSET
(integer_expr)] AS val ) );
select factorial(10);

SQL to MDX conversion

I have this where clause in sql language:
where (cond1=1 or cond2=1) and cond3=1
How can I get this result in MDX with the slicing(condition into the where)?
{[cond1].&[1],[cond2].&[1]} /*and*/ {[cond3].&[1]}
Thanks
Try to use a subcube:
Select
-- YOUR SELECTED MEASURES AND DIMENSIONS
From
(
Select
{[cond1].&[1],[cond2].&[1]} on 0
,{[cond3].&[1]} on 1
-- ,{more slices} on x
From [CubeName]
)
Hope this help!
You can use subcube expression as stated above, but this is not the only option. If you use subcube, you would increase query performance greatly (assuming the fact you don't perform crossjoins in it).
You can also use general WHERE keyword after last expression that returns cube:
select
{ .. } on 0,
{ .. } on 1
from (select { [Dim1].[X].allmembers } on 0)
where ([Dim2].[Y].&[Y1])
Or:
select
{ .. } on 0,
{ .. } on 1
from (select { [Dim1].[X].allmembers } on 0)
where {[DimTime].[Time].[Year].&[2001] : [DimTime].[Time].[Year].&[2015]}
This is applied at the end of execution, which means performance may decrease. However, if you need to apply external filter to all axis, this is the option you need.
Another way to filter member values is using tuple expressions:
with member LastDateSale as ( (Tail(EXISTING [DimTime].[Time].[Dates].members,1), [Measures].[ActualSales]) )
This will take your DimTime axis, apply external filter, get the last element from it and calculate [ActualSales] for it, if possible.

NormDist & Square Root calculation in SQL

Please check the below screenshot for data classification.
Just wondering is there any easy way to calculate NORMDIST, SQRT & PRODUCT using SQL commands just as like as I did below to calculate the AVG & VAR.
Please note the below code I was using for another purpose and doesn't suit the screenshot values.
SELECT state, AVG([v2t] * 1.0) FROM portability WHERE state = 'Queensland' GROUP BY state
SELECT state, STDEV([v2t] * 1.0) FROM portability WHERE state = 'Queensland' GROUP BY state
Assuming Oracle:
In Oracle/PLSQL, the sqrt function:
sqrt( n )
For Example
sqrt(9) would return 3
sqrt(37) would return 6.08276253029822
sqrt(5.617) would return 2.37002109695251
For NormDist, try CUM_DIST. The aggregate functions are documented in
http://docs.oracle.com/cd/E11882_01/server.112/e10592/functions003.htm#SQLRF20035
I do not believe Oracle has a function for product.

Mdx Sum returns non integer value

When have a issue at work where the value returned by the SUM() function isn't treated like a "normal" number when using the value returned together with the Round() function.
Try this MDX for example
WITH
MEMBER SomeNumber AS 0.595
SET SomeNumberSet AS
{[SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber] }
MEMBER SomeNumberSum AS
Round(SUM([SomeNumberSet], [Measures].[SomeNumber]) / 8, 2)
SELECT [SomeNumberSum] ON 0
FROM [SomeCube]
This code returns 0.59, the sum of sets are 4,76, which are then divided by 8 = 0,595. Since MDX is using Bankers rounding this SHOULD be rounded to 0.60.
Just using Round(0,595) gives us the correct result.
Whats even more strange is that if we in the set only uses the SomeNumber 6 times or less and in the Round Function divide with the same multiplier we get 0.6 (which is correct)
Also, if I wrap the Sum() with the StrToValue() function, it works, even if I use more than 5 SomeNumbers in the set
Whats going on?!
Not sure is the actual answer you're looking for. The issue you've has to do with numerical precision, aka rounding errors, more than with MDX.
If you're in Java, run the following test :
public void testNumeric()
{
double sum = 0.0;
double value = 0.595;
for (int i = 0; i < 8; i++)
{
sum += value;
}
double prod = value * 8;
assertEquals(sum / 8, prod / 8);
}
The assert will fail, strange no ?
Result : expected:<0.5949999999999999> but was:<0.595>
The first one, sum, is how mdx is calculating the value. You got a slight difference, but it is enough for changing the result of the ROUND().
Is there a solution ?
Strictly speaking no, it's an error due to the very nature of the numeric calculation with computers. Practically you can cheat a bit round first to 10 - ROUND(ROUND(MyNumber,10),2), not brillant (10 is an example).
If you're interested start in wikipedia from here
According with Chris Webb, this behaviour is intentional:
http://www.techonthenet.com/access/functions/numeric/round.php
If you have Excel libraries, this works:
WITH
MEMBER SomeNumber AS 0.595
SET SomeNumberSet AS
{[SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber] }
MEMBER SomeNumberSum AS
Excel!Round(SUM([SomeNumberSet], [Measures].[SomeNumber]) / 8, 2)
SELECT [SomeNumberSum] ON 0
FROM [Adventure Works]