Related
Suppose I have a function phi(x1,x2)=k1*x1+k2*x2 which I have evaluated over a grid where the grid is a square having boundaries at -100 and 100 in both x1 and x2 axis with some step size say h=0.1. Now I want to calculate this sum over the grid with which I'm struggling:
What I was trying :
clear all
close all
clc
D=1; h=0.1;
D1 = -100;
D2 = 100;
X = D1 : h : D2;
Y = D1 : h : D2;
[x1, x2] = meshgrid(X, Y);
k1=2;k2=2;
phi = k1.*x1 + k2.*x2;
figure(1)
surf(X,Y,phi)
m1=-500:500;
m2=-500:500;
[M1,M2,X1,X2]=ndgrid(m1,m2,X,Y)
sys=#(m1,m2,X,Y) (k1*h*m1+k2*h*m2).*exp((-([X Y]-h*[m1 m2]).^2)./(h^2*D))
sum1=sum(sys(M1,M2,X1,X2))
Matlab says error in ndgrid, any idea how I should code this?
MATLAB shows:
Error using repmat
Requested 10001x1001x2001x2001 (298649.5GB) array exceeds maximum array size preference. Creation of arrays greater
than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference
panel for more information.
Error in ndgrid (line 72)
varargout{i} = repmat(x,s);
Error in new_try1 (line 16)
[M1,M2,X1,X2]=ndgrid(m1,m2,X,Y)
Judging by your comments and your code, it appears as though you don't fully understand what the equation is asking you to compute.
To obtain the value M(x1,x2) at some given (x1,x2), you have to compute that sum over Z2. Of course, using a numerical toolbox such as MATLAB, you could only ever hope to compute over some finite range of Z2. In this case, since (x1,x2) covers the range [-100,100] x [-100,100], and h=0.1, it follows that mh covers the range [-1000, 1000] x [-1000, 1000]. Example: m = (-1000, -1000) gives you mh = (-100, -100), which is the bottom-left corner of your domain. So really, phi(mh) is just phi(x1,x2) evaluated on all of your discretised points.
As an aside, since you need to compute |x-hm|^2, you can treat x = x1 + i x2 as a complex number to make use of MATLAB's abs function. If you were strictly working with vectors, you would have to use norm, which is OK too, but a bit more verbose. Thus, for some given x=(x10, x20), you would compute x-hm over the entire discretised plane as (x10 - x1) + i (x20 - x2).
Finally, you can compute 1 term of M at a time:
D=1; h=0.1;
D1 = -100;
D2 = 100;
X = (D1 : h : D2); % X is in rows (dim 2)
Y = (D1 : h : D2)'; % Y is in columns (dim 1)
k1=2;k2=2;
phi = k1*X + k2*Y;
M = zeros(length(Y), length(X));
for j = 1:length(X)
for i = 1:length(Y)
% treat (x - hm) as a complex number
x_hm = (X(j)-X) + 1i*(Y(i)-Y); % this computes x-hm for all m
M(i,j) = 1/(pi*D) * sum(sum(phi .* exp(-abs(x_hm).^2/(h^2*D)), 1), 2);
end
end
By the way, this computation takes quite a long time. You can consider either increasing h, reducing D1 and D2, or changing all three of them.
I'm trying to clamp a number to the lower value of a series of numbers. For instance, if I have a series (sorry for the bad notation)
[pq] where p is any integer and q is any positive number.
Say if q is 50 my series will be ...-150, -100, -50, 0, 50, 100, 150...
Now what I'd like is to have a function f(y) which'll clamp any number to the next lowest number in the series.
For example, if I had the number 37 I'd be expecting the f(37) = 0 and I'd be expecting f(-37) = -50.
I've tried many algorithms involving modulus and integer division but I can't seem to figure it out. The latest I've tried is for example
(37 / q) * q which works great for positive numbers but doesn't work for any number between -50 and 0.
I've also tried ((37 - q) / q) * q but this won't work for negative cases which land exactly in the series.
EDIT
Assume that I do not have the entire series but only the multiplier p of the series.
You simply need to divide y by q using integer Euclidean division and then multiply the result by q again.
f(y) = (y / q) * q
where / represents Euclidean division.
In programming languages that do not immediately support Euclidean division you will have to either implement it manually or adjust the result of whatever division the language supports.
For example, in C and C++ Euclidean division for positive divisor q can be implemented through the native "Fortran-style" division as
(y >= 0 ? y : y - q + 1) / q
so in C or C++ the whole expression will look as
f(y) = (y >= 0 ? y : y - q + 1) / q * q
For 37 you get
f(37) = 37 / 50 * 50 = 0
For -37 you get
f(-37) = (-37 - 50 + 1) / 50 * 50 = -86 / 50 * 50 = -50
If you want a purely mathematical way, with no consideration given to computational efficiency, you could shift the input p into the positive integer range by adding a positive integer that is greater than or equal to |p| and is a multiple of q, and then shift it back by subtracting afterwards. p^2*q satisfies this.
This gives:
((p + p^2*q) / q) * q - p^2*q
You can subtract the modulus result once you've ensured it's positive. In some languages it will always be positive, but if not:
mod = p % q
positive_mod = (mod + q) % q
answer = p - positive_mod
Result in C++: https://ideone.com/kIuit8
Result in Python: https://ideone.com/w6wUgZ
I have a variable, between 0 and 1, which should dictate the likelyhood that a second variable, a random number between 0 and 1, is greater than 0.5. In other words, if I were to generate the second variable 1000 times, the average should be approximately equal to the first variable's value. How do I make this code?
Oh, and the second variable should always be capable of producing either 0 or 1 in any condition, just more or less likely depending on the value of the first variable. Here is a link to a graph which models approximately how I would like the program to behave. Each equation represents a separate value for the first variable.
You have a variable p and you are looking for a mapping function f(x) that maps random rolls between x in [0, 1] to the same interval [0, 1] such that the expected value, i.e. the average of all rolls, is p.
You have chosen the function prototype
f(x) = pow(x, c)
where c must be chosen appropriately. If x is uniformly distributed in [0, 1], the average value is:
int(f(x) dx, [0, 1]) == p
With the integral:
int(pow(x, c) dx) == pow(x, c + 1) / (c + 1) + K
one gets:
c = 1/p - 1
A different approach is to make p the median value of the distribution, such that half of the rolls fall below p, the other half above p. This yields a different distribution. (I am aware that you didn't ask for that.) Now, we have to satisfy the condition:
f(0.5) == pow(0.5, c) == p
which yields:
c = log(p) / log(0.5)
With the current function prototype, you cannot satisfy both requirements. Your function is also asymmetric (f(x, p) != f(1-x, 1-p)).
Python functions below:
def medianrand(p):
"""Random number between 0 and 1 whose median is p"""
c = math.log(p) / math.log(0.5)
return math.pow(random.random(), c)
def averagerand(p):
"""Random number between 0 and 1 whose expected value is p"""
c = 1/p - 1
return math.pow(random.random(), c)
You can do this by using a dummy. First set the first variable to a value between 0 and 1. Then create a random number in the dummy between 0 and 1. If this dummy is bigger than the first variable, you generate a random number between 0 and 0.5, and otherwise you generate a number between 0.5 and 1.
In pseudocode:
real a = 0.7
real total = 0.0
for i between 0 and 1000 begin
real dummy = rand(0,1)
real b
if dummy > a then
b = rand(0,0.5)
else
b = rand(0.5,1)
end if
total = total + b
end for
real avg = total / 1000
Please note that this algorithm will generate average values between 0.25 and 0.75. For a = 1 it will only generate random values between 0.5 and 1, which should average to 0.75. For a=0 it will generate only random numbers between 0 and 0.5, which should average to 0.25.
I've made a sort of pseudo-solution to this problem, which I think is acceptable.
Here is the algorithm I made;
a = 0.2 # variable one
b = 0 # variable two
b = random.random()
b = b^(1/(2^(4*a-1)))
It doesn't actually produce the average results that I wanted, but it's close enough for my purposes.
Edit: Here's a graph I made that consists of a large amount of datapoints I generated with a python script using this algorithm;
import random
mod = 6
div = 100
for z in xrange(div):
s = 0
for i in xrange (100000):
a = (z+1)/float(div) # variable one
b = random.random() # variable two
c = b**(1/(2**((mod*a*2)-mod)))
s += c
print str((z+1)/float(div)) + "\t" + str(round(s/100000.0, 3))
Each point in the table is the result of 100000 randomly generated points from the algorithm; their x positions being the a value given, and their y positions being their average. Ideally they would fit to a straight line of y = x, but as you can see they fit closer to an arctan equation. I'm trying to mess around with the algorithm so that the averages fit the line, but I haven't had much luck as of yet.
SO,
The problem
I have two integers, which are in first case, positive, and in second case - just any integers. I need to create a map function F from them to some another integer value, which will be:
Result should be integer value. For first case (x>0, y>0), positive integer value
Symmetric. That means F(x, y) = F(y, x)
Unique. That means F(x0, y0) = F(x1, y1) <=> (x0 = x1 ^ y0 = y1) V (y0 = x1 ^ x0 = y1)
My approach
At first glance, for positive integers we could use expression like F(x, y) = x2 + y2, but that will fail - for example, 892 + 232 = 132 + 912 As for second (common) case - that's even more complicated.
Use-case
That may be useful when dealing with some things, which supposed to be order-independent and need to be unique. For example, if we want to find cartesian product of many arrays and we want result to be unique independent of order, i.e. <x,z,y> is equal to <x,y,z>. It may be done with:
function decartProductPair($one, $two, $unique=false)
{
$result = [];
for($i=0; $i<count($one); $i++)
{
for($j=0; $j<count($two); $j++)
{
if($unique)
{
if($i!=$j)
{
$result[$i*$i+$j*$j]=array_merge((array)$one[$i],(array)$two[$j]);
// ^
// |
// +----//this is the place where F(i,j) is needed
}
}
else
{
$result[]=array_merge((array)$one[$i], (array)$two[$j]);
}
}
}
return array_values($result);
}
Another use-case is to properly group sender and receiver in some SQL table, so that different senders/receivers will be differed while they should stay symmetric. Something like:
SELECT
COUNT(1) AS message_count,
sender,
receiver
FROM
test
GROUP BY
-- this is the place where F(sender, receiver) is needed:
sender*sender + receiver*receiver
(By posting samples I wanted to show that issue is certainly related to programming)
The question
As mentioned, the question is - what can be used as F? I want as simple F as it's possible. Keep in mind two cases:
Integer x>0, y>0. F(x,y) > 0
Any integer x, y and so any integer F(x,y) as a result
May be F isn't just an expression - but some algorithm to find desired result for any x,y (so tagging with algorithm too). However, expression is better because it's more like that it will be able to use that expression in SQL or PHP or whatever. Feel free to edit tagging because I'm not sure if two tags here is enough
Most simple solution: f(x,y) = x^5 + y^5
No positive integer is known which can be written as the sum of two fifth powers in more than one way.
As for now, this is unsolved math problem.
You need a MAX_INTEGER constant, and the result will need to hold MAX_INTEGER**2 (say: be a long, if both are int's). In that case, one such function is:
f(x,y) = min(x,y)*MAX_INTEGER + max(x,y)
But I propose a different solution: use a hash function (say md5) of the string resulting from the concatenation of str(min(x,y)), a separator (say ".") and str(max(x,y)). That is:
f(x,y) = md5(str(min(x,y)) + "." + str(max(x,y)))
It is not unique, but collisions are very rare, and probably OK for most use cases. If still worried about collisions, save the actualy {x,y} along with f(x,y), and check if collisions happened.
Sort input numbers and interleave their bits:
x = 5
y = 3
Step 1. Sorting: 3, 5
Step 2. Mixing bits: 11, 101 -> 1_1_, 1_0_1 -> 11011 = 27
So, F(3, 5) = 27
A compact representation is x*(x+3)/2 + y*(x+1) + (y*(y-1))/2, which comes from an arrangement like this:
x->
y 0 1 3 6 10 15
| 2 4 7 11 16
v 5 8 12 17
9 13 18
14 19
20
According to [Stackoverflow:mapping-two-integers-to-one-in-a-unique-and-deterministic-way][1], if we symmetrize the formula we would have the following:
(x + y) * (x + y + 1) / 2 + min(x, y)
This might just work. For
(x + y) * (x + y + 1) / 2 + x
is unique, then the first formula is also unique.
[1]: Mapping two integers to one, in a unique and deterministic way
So I'm creating a Activation class for a VB6 project and I've run into a brain fart. I've designed how I want to generate the Serial Number for this particular product in a following way.
XXXX-XXXX-XXXX-XXXX
Each group of numbers would be representative of data that I can read if I'm aware of the matching document that allows me to understand the codes with the group of digits. So for instance the first group may represent the month that the product was sold to a customer. But I can't have all the serial numbers in January all start with the same four digits so there's some internal math that needs to be done to calculate this value. What I've landed on is this:
A B C D = digits in the first group of the serial number
(A + B) - (C + D) = #
Now # would relate to a table of Hex values that would then represent the month the product was sold. Something like...
1 - January
2 - February
3 - March
....
B - November
C - December
My question lies here - if I know I need the total to equal B(11) then how exactly can I code backwards to generate (A + B) - (C + D) = B(11)?? It's a pretty simple equation, I know - but something I've just ran into and can't seem to get started in the right direction. I'm not asking for a full work-up of code but just a push. If you have a full solution available and want to share I'm always open to learning a bit more.
I am coding in VB6 but VB.NET, C#, C++ solutions could work as well since I can just port those over relatively easily. The community help is always greatly appreciated!
There's no single solution (you have one equation with four variables). You have to pick some random numbers. Here's one that works (in Python, but you get the point):
from random import randint
X = 11 # the one you're looking for
A_plus_B = randint(X, 30)
A = randint(max(A_plus_B - 15, 0), min(A_plus_B, 15))
B = A_plus_B - A
C_plus_D = A_plus_B - X
C = randint(max(C_plus_D - 15, 0), min(C_plus_D, 15))
D = C_plus_D - C
I assume you allow hexadecimal digits; if you just want 0 to 9, replace 15 by 9 and 30 by 18.
OK - pen and paper is always the solution... so here goes...
Attempting to find what values should be for (A + B) - (C + D) to equal a certain number called X. First I know that I want HEX values so that limits me to 0-F or 0-15. From there I need a better starting place so I'll generate a random number that will represent the total of (A + B), we'll call this Y, but not be lower than value X. Then subtract from that number Y value of X to determine that value that will represent (C + D), which we'll call Z. Use similar logic to break down Y and Z into two numbers each that can represent (A + B) = Y and (C + D) = Z. After it's all said and done I should have a good randomization of creating 4 numbers that when plugged into my equation will return a suitable result.
Just had to get past the brain fart.
This may seem a little hackish, and it may not take you where you're trying to go. However it should produce a wider range of values for your key strings:
Option Explicit
Private Function MonthString(ByVal MonthNum As Integer) As String
'MonthNum: January=1, ... December=12. Altered to base 0
'value for use internally.
Dim lngdigits As Long
MonthNum = MonthNum - 1
lngdigits = (Rnd() * &H10000) - MonthNum
MonthString = Right$("000" & Hex$(lngdigits + (MonthNum - lngdigits Mod 12)), 4)
End Function
Private Function MonthRecov(ByVal MonthString As String) As Integer
'Value returned is base 1, i.e. 1=January.
MonthRecov = CInt(CLng("&H" & MonthString) Mod 12) + 1
End Function
Private Sub Form_Load()
Dim intMonth As Integer
Dim strMonth As String
Dim intMonthRecov As Integer
Dim J As Integer
Randomize
For intMonth = 1 To 12
For J = 1 To 2
strMonth = MonthString(intMonth)
intMonthRecov = MonthRecov(strMonth)
Debug.Print intMonth, strMonth, intMonthRecov, Hex$(intMonthRecov)
Next
Next
End Sub