Recurrence relation solution for relations with two interdependent variables - recurrence

I came across the following problem in an online challenge.
Consider the following vectors:
x = [3, 4, ...]
y = [2, 3, ...]
Such that for i >= 2:
x[i] = x[i-1] + 3 * y[i-2]
y[i] = 2 * y[i-1] + 2 * x[i-2]
What is x[10^15] ?
While the problem has a very straightforward solution, the problem is the 10^15 value which cannot be calculated in a small time. Only thing I can think of is that we have to derive a polynomial from the recurrence relation - However this isn't easy to do. Am I missing something?

The problem statement can be express as matrix multiplication as follows:
A= [
[1, 0, 0, 3],
[1, 0, 0, 0],
[0, 2, 2, 0],
[0, 0, 1, 0]
]
[xn+1, xn, yn+1, yn] = A*[xn, xn-1, yn, yn-1]
=> [xn+1, xn, yn+1, yn] = A^(n-1) * [x1, x0, y1, y0]
[x1, x0, y1, y0] = [4, 3, 3, 2]
While not mentioned in the problem, since the matrix multiplication exceeds integer limits, the solution needs to be expressed in as remainder of some prime number. Let the prime number be 1000000007. But how can we not exceed the integer limits while multiplying? Consider the following:
(X * Y) mod p = ((X mod p) * (Y mod p)) mod p
Now, X = A^n
Let, A^n mod p = B
Now, B = B mod p
So,
(X * Y) mod p =
((X mod p) * (Y mod p)) mod p
=> ((A^n mod p) * (Y mod p)) mod p
=> ( B * (Y mod p)) mod p
=> ((B mod p) * (Y mod p)) mod p
=> (B * Y) mod p
So a simple python implementation would be:
import numpy as np
p = 1000000007
A= np.array([
[1, 0, 0, 3],
[1, 0, 0, 0],
[0, 2, 2, 0],
[0, 0, 1, 0]
])
Y = np.array([4, 3, 3, 2])
# We will use binary exponentiation for fast matrix multiplication
# See: https://cp-algorithms.com/algebra/binary-exp.html
# The `power` list is the array of A's powers needed for that
powers = []
powers.append(A % p)
for i in range(1, 50): # Till 50 since 10^15 ~= 2^50
Ap = powers[i - 1]
powers.append(Ap.dot(Ap) % p)
def solve(n):
pow_of_a = n - 3
index = 0
prod = np.identity(4)
while (pow_of_a > 0):
if (pow_of_a & 1) == 1:
prod = prod.dot(powers[index])
pow_of_a >>= 1
index += 1
B = prod % p
print(B.dot(Y) % p)

Related

Performing Laplace transform on non-continuous function in Maxima

I am calculating the following function's Laplace transform, but I get some strange output with limit and realpart etc on (%t5) and (%t6). What I expect is something like a_n = 0 and b_n = -1/(n*%pi).
Why is this happening? Am I defining the function at (%i1) incorrectly? Or is this a limitation of Maxima?
(%i1) f(t) := mod(t, 1);
(%o1) f(t) := mod(t, 1)
(%i2) plot2d(f(t), [t, -2, 2]);
(%o2) [/tmp/maxout1266174.gnuplot_pipes]
(%i3) load(fourie);
(%o3) /usr/share/maxima/5.43.0/share/calculus/fourie.mac
(%i4) fourier(f(t), t, 1);
1
(%t4) a = -
0 2
/
[
(%t5) a = limit I cos(%pi n t) realpart(floor(t)) dt
n t -> - 1 ]
/
/
[
- limit I cos(%pi n t) realpart(floor(t)) dt
t -> 1 ]
/
/
[
(%t6) b = (- limit I sin(%pi n t) realpart(floor(t)) dt)
n t -> 1 ]
/
/
[ 2 sin(%pi n) 2 cos(%pi n)
+ limit I sin(%pi n t) realpart(floor(t)) dt + ------------ - ------------
t -> - 1 ] 2 2 %pi n
/ %pi n
(%o6) [%t4, %t5, %t6]
(%i7)

Nonzero vector in quantifier

I want to verify a formula of the form:
Exists p . ForAll x != 0 . f(x, p) > 0
An implementation (that isn't working) is the following:
def f0(x0, x1, x, y):
return x1 ** 2 * y + x0 ** 2 * x
s = Solver()
x0, x1 = Reals('x0 x1')
p0, p1 = Reals('p0 p1')
s.add(Exists([p0, p1],
ForAll([x0, x1],
f0(x0, x1, p0, p1) > 0
)
))
#s.add(Or(x0 != 0, x1 != 0))
while s.check() == sat:
m = s.model()
m.evaluate(x0, model_completion=True)
m.evaluate(x1, model_completion=True)
m.evaluate(p0, model_completion=True)
m.evaluate(p1, model_completion=True)
print m
s.add(Or(x0 != m[x0], x1 != m[x1]))
The formula isn't satisfied.
With f0() >= 0, the only output is (0, 0).
I want to have f0() > 0 and constrain (x0, x1) != (0, 0).
Something I'd expect is: p0, p1 = 1, 1 or 2, 2 for instance, but I don't know how to remove 0, 0 from the possible values for x0, x1.
Following up on Levent's reply. During the first check, Z3 uses a custom decision procedure that works with the quantifiers. In incremental mode it falls back to something that isn't a decision procedure. To force the one-shot solver try the following:
from z3 import *
def f0(x0, x1, x, y):
return x1 * x1 * y + x0 * x0 * x
p0, p1 = Reals('p0 p1')
x0, x1 = Reals('x0 x1')
fmls = [ForAll([x0, x1], Implies(Or(x0 != 0, x1 != 0), f0(x0, x1, p0, p1) > 0))]
while True:
s = Solver()
s.add(fmls)
res = s.check()
print res
if res == sat:
m = s.model()
print m
fmls += [Or(p0 != m[p0], p1 != m[p1])]
else:
print "giving up"
break
You'd simply write that as an implication inside the quantification. I think you're also mixing up some of the variables in there. The following seems to capture your intent:
from z3 import *
def f0(x0, x1, x, y):
return x1 * x1 * y + x0 * x0 * x
s = Solver()
p0, p1 = Reals('p0 p1')
x0, x1 = Reals('x0 x1')
s.add(ForAll([x0, x1], Implies(Or(x0 != 0, x1 != 0), f0(x0, x1, p0, p1) > 0)))
while True:
res = s.check()
print res
if res == sat:
m = s.model()
print m
s.add(Or(p0 != m[p0], p1 != m[p1]))
else:
print "giving up"
break
Of course, z3 isn't guaranteed to find you any solutions; though it seems to manage one:
$ python a.py
sat
[p1 = 1, p0 = 1]
unknown
giving up
Once you use quantifiers all bets are off, as the logic becomes semi-decidable. Z3 is doing a good job here and returning one solution, and then it's giving up. I don't think you can expect anything better, unless you use some custom decision procedures.

z3 and interpretation of floating point coefficients

I was playing with a small multi-objective integer programming problem:
In Z3 (using the Python bindings) we can state this very elegantly:
from z3 import *
x1,x2 = Ints('x1 x2')
z1,z2 = Reals('z1 z2')
opt = Optimize()
opt.set(priority='pareto')
opt.add(x1 >= 0, x2 >=0, x1 <= 2, x2 <= 2)
opt.add(x1 <= 2*x2)
# this version is ok:
# opt.add(z1 == x1 - 2*x2, z2 == -x1 + 3*x2)
# this truncates coefficients (round down to integer):
# opt.add(z1 == 0.5*x1 - 1.0*x2, z2 == -0.5*x1 + 1.5*x2)
# this one seems to work:
# opt.add(z1 == 0.5*ToReal(x1) - 1.0*ToReal(x2), z2 == -0.5*ToReal(x1) + 1.5*ToReal(x2))
opt.add(z1 == x1 - 2*x2, z2 == -x1 + 3*x2)
f1 = opt.maximize(z1)
f2 = opt.maximize(z2)
while opt.check() == sat:
print(opt.model())
This solves correctly and gives:
[x1 = 2, x2 = 1, z2 = 1, z1 = 0]
[x1 = 0, x2 = 2, z2 = 6, z1 = -4]
[x1 = 2, x2 = 2, z2 = 4, z1 = -2]
[x1 = 1, x2 = 1, z2 = 2, z1 = -1]
[x1 = 1, x2 = 2, z2 = 5, z1 = -3]
As my real problem has floating point coefficients for the objectives, I divided the objectives by 2:
opt.add(z1 == 0.5*x1 - 1.0*x2, z2 == -0.5*x1 + 1.5*x2)
This model should give the same five solutions for the x variables. However, when we run it, we see some wrong results:
[x1 = 0, x2 = 0, z2 = 0, z1 = 0]
[x1 = 0, x2 = 2, z2 = 2, z1 = -2]
[x1 = 0, x2 = 1, z2 = 1, z1 = -1]
When I print opt I can see where things go wrong:
(assert (= z1 (to_real (- (* 0 x1) (* 1 x2)))))
(assert (= z2 (to_real (+ (* 0 x1) (* 1 x2)))))
The coefficients are silently truncated and converted to integers: 0.5 arrived as 0 and 1.5 became 1.
A workaround seems to be:
opt.add(z1 == 0.5*ToReal(x1) - 1.0*ToReal(x2), z2 == -0.5*ToReal(x1) + 1.5*ToReal(x2))
This converts the floating point coefficient to their rational equivalents:
(assert (= z1 (- (* (/ 1.0 2.0) (to_real x1)) (* 1.0 (to_real x2)))))
(assert (= z2 (+ (* (- (/ 1.0 2.0)) (to_real x1)) (* (/ 3.0 2.0) (to_real x2)))))
Now 0.5 becomes (/ 1.0 2.0) and 1.5 is represented by (/ 3.0 2.0).
My questions are:
Is this truncation "as designed"?
Is my workaround the correct way to go about this? Or should I avoid floating point coefficients altogether?
The printed rational number (/ 1.0 2.0) seems to hint there are still floating point numbers involved. Is this really (/ 1 2)? (I assume these are actually bigints).
I think you essentially answered your own question. Bottom line is that Python is an untyped language, so when you mix-and-match different typed operands to arithmetic operators, you are at the mercy of the library as it will "match" these types for you, and it is not surprising that it does the wrong thing here. In SMT-Lib2, or any other more strongly-typed binding, you'd instead get a type error.
Never mix types in arithmetic, and always be explicit. Or, better yet, use an interface that enforces this in its type system, instead of implicitly coercing constants. So, short answer is, yes; this is by design, but not because of any deep reason, but rather how the Python bindings behave.
Here's a simpler demo:
>>> from z3 import *
>>> x = Int('x')
>>> y = Real('y')
>>> x*2.5
x*2
>>> y*2.5
y*5/2
So, it appears that once you have a declared variable, then the constants that interact with them automatically coerce to the type of that variable. But I wouldn't count on that at all: It's best to be always explicit when you are working in an untyped setting.

How to sum "any three elements" in a tuple in F#

I recently started learning how to program in F# and I have an assignment that is giving me some serious headaches.
I have to make a function that takes two arguments, an integer and a five element tuple of integers, and returns true if the sum of any three elements of the tuple is greater than the first argument, else false.
I started designing my code this way
{
let t3 = (1, 2, 3, 4, 5)
let intVal = 1
let check intVal t3 =
for t3
if (*sum of any three elements*) > intVal then true
else false
}
but at this point I am stuck and do not know how to proceed.
Easy way define - sort elements of tuple and compare with sum last three elements (ascending sort) :
let inline isAnyThreeGreaterThan2 limit (x1, x2, x3, x4, x5) =
[x1;x2;x3;x4;x5] |> List.sort |> Seq.skip 2 |> Seq.sum > limit
Example:
isAnyThreeGreaterThan2 15 (1, 2, 5, 5, 5) |> printfn "%A"
isAnyThreeGreaterThan2 14 (1, 2, 5, 5, 5) |> printfn "%A"
isAnyThreeGreaterThan2 15 (1, 2, 5, 5, 6) |> printfn "%A"
isAnyThreeGreaterThan2 15 (1, 2, 3, 4, 5) |> printfn "%A"
isAnyThreeGreaterThan2 12 (1, 2, 3, 4, 5) |> printfn "%A"
isAnyThreeGreaterThan2 11 (1, 2, 3, 4, 5) |> printfn "%A"
Print:
false
true
true
false
false
true
Link:
https://dotnetfiddle.net/7XR1ZA
It could be solved by converting the tuple into an array, getting the possible combinations out of it, summing those combinations and then verify if the any of the sums is greater than your parameter
(1,2,3,4,5)
|> Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields
|> Array.toList
//Implementing this is left as and exercise to the reader
|> combinations 3
//converts the obj list as a int list and then sums the elements
|> List.map (fun x -> x |> List.map unbox<int> |> List.sum)
//Verifies if any sum is greater than intVal
|> List.exists (fun x -> x > intVal)
Something like this ought to do it:
let cross3 l1 l2 l3 =
[
for x in l1 do
for y in l2 do
for z in l3 do
yield x, y, z ]
module Tuple3 =
let distinct (x, y, z) =
let l = [x; y; z]
l |> List.distinct |> List.length = l.Length
let snd (x, y, z) = snd x, snd y, snd z
let inline sum (x, y, z) = x + y + z
let inline isAnyThreeGreaterThan limit (x1, x2, x3, x4, x5) =
let l = [x1; x2; x3; x4; x5] |> List.indexed
let legalCombinations =
cross3 l l l
|> List.filter Tuple3.distinct
|> List.map Tuple3.snd
legalCombinations |> List.exists (fun t3 -> Tuple3.sum t3 > limit)
Since this is an assignment, I'll leave it as an exercise to understand what's going on, but here's a sample FSI session:
> isAnyThreeGreaterThan 15 (1, 2, 5, 5, 5);;
val it : bool = false
> isAnyThreeGreaterThan 14 (1, 2, 5, 5, 5);;
val it : bool = true
> isAnyThreeGreaterThan 15 (1, 2, 5, 5, 6);;
val it : bool = true
> isAnyThreeGreaterThan 15 (1, 2, 3, 4, 5);;
val it : bool = false
> isAnyThreeGreaterThan 12 (1, 2, 3, 4, 5);;
val it : bool = false
> isAnyThreeGreaterThan 11 (1, 2, 3, 4, 5);;
val it : bool = true

Divide a Point in Elliptic Curve Cryptography

I'm using Elliptic Curve to design a security system. P is a point on elliptic curve. The receiver must obtain P using formula k^-1(kP). The receiver does not know P but knows k. I need to compute k^-1(R) where R=kP. How can I do this using Point Multiplication or Point Addition.
I suggest first learning a bit more about ECC (for example, read some of Paar's book and listen to his course at http://www.crypto-textbook.com/) before tackling something this complex. For this particular question, ask yourself: "What does the inverse of k mean?"
Very interesting question you have! I was happy to implement from scratch Python solution for your task, see code at the bottom of my answer.
Each elliptic curve has an integer order q. If we have any point P on curve then it is well known that q * P = Zero, in other words multiplying any point by order q gives zero-point (infinity point).
Multiplying zero (infinity) point by any number gives zero again, i.e. j * Zero = Zero for any integer j. Adding any point P to zero-point gives P, i.e. Zero + P = P.
In our task we have some k such that R = k * P. We can very easily (very fast) compute Modular Inverse of k modulo order q, using for example Extended Euclidean Algorithm.
Inverse of k modulo q by definition is such that k * k^-1 = 1 (mod q), which by definition of modulus is equal k * k^-1 = j * q + 1 for some integer j.
Then k^-1 * R = k^-1 * k * P = (j * q + 1) * P = j * (q * P) + P = j * Zero + P = Zero + P = P. Thus multiplying R by k^-1 gives P, if k^-1 is inverse of k modulo q.
You can read about point addition and multiplication formulas on this Wiki.
Lets now check our formulas in Python programming language. I decided to implement from scratch simple class ECPoint, which implements all curve operations (addition and multiplication), see code below.
We take any ready-made curve, for example most popular 256-bit curve secp256k1, which is used in Bitcoin. Its parameters can be found here (this doc contains many other popular standard curves), also you can read about this specific curve on Bitcoin Wiki Page.
Following code is fully self-contained Python script, doesn't need any external dependencies and modules. You can run it straight away on any computer. ECPoint class implements all curve arithmetics. Function test() does following operations: we take standard secp256k1 params with some base point G, we compute any random point P = random * G, then we generate random k, compute R = k * P, compute modular inverse k^-1 (mod q) by using function modular_inverse() (which uses extended Euclidean algorithm egcd()), compute found_P = k^-1 * R and check that it is equal to P, i.e. check that k^-1 * R == P, print resulting k^-1 * R. All random values are 256-bit.
Try it online!
def egcd(a, b):
# https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
ro, r, so, s, to, t = a, b, 1, 0, 0, 1
while r != 0:
ro, (q, r) = r, divmod(ro, r)
so, s = s, so - q * s
to, t = t, to - q * t
return ro, so, to
def modular_inverse(a, mod):
# https://en.wikipedia.org/wiki/Modular_multiplicative_inverse
g, s, t = egcd(a, mod)
assert g == 1, 'Value not invertible by modulus!'
return s % mod
class ECPoint:
#classmethod
def Int(cls, x):
return int(x)
#classmethod
def std_point(cls, name):
if name == 'secp256k1':
# https://en.bitcoin.it/wiki/Secp256k1
# https://www.secg.org/sec2-v2.pdf
p = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFC2F
a = 0
b = 7
x = 0x79BE667E_F9DCBBAC_55A06295_CE870B07_029BFCDB_2DCE28D9_59F2815B_16F81798
y = 0x483ADA77_26A3C465_5DA4FBFC_0E1108A8_FD17B448_A6855419_9C47D08F_FB10D4B8
q = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_BAAEDCE6_AF48A03B_BFD25E8C_D0364141
else:
assert False
return ECPoint(x, y, a, b, p, q)
def __init__(self, x, y, A, B, N, q, *, prepare = True):
if prepare:
N = self.Int(N)
A, B, x, y, q = [self.Int(e) % N for e in [A, B, x, y, q]]
assert (4 * A ** 3 + 27 * B ** 2) % N != 0
assert (y ** 2 - x ** 3 - A * x - B) % N == 0, (
x, y, A, B, N, (y ** 2 - x ** 3 - A * x) % N)
assert N % 4 == 3
assert y == pow(x ** 3 + A * x + B, (N + 1) // 4, N)
self.A, self.B, self.N, self.x, self.y, self.q = A, B, N, x, y, q
def __add__(self, other):
A, N = self.A, self.N
Px, Py, Qx, Qy = self.x, self.y, other.x, other.y
if Px == Qx and Py == Qy:
s = ((Px * Px * 3 + A) * self.inv(Py * 2, N)) % N
else:
s = ((Py - Qy) * self.inv(Px - Qx, N)) % N
x = (s * s - Px - Qx) % N
y = (s * (Px - x) - Py) % N
return ECPoint(x, y, A, self.B, N, self.q, prepare = False)
def __rmul__(self, other):
other = self.Int(other - 1)
r = self
while True:
if other & 1:
r = r + self
if other == 1:
return r
other >>= 1
self = self + self
#classmethod
def inv(cls, a, n):
return modular_inverse(a, n)
def __repr__(self):
return str(dict(x = self.x, y = self.y, A = self.A,
B = self.B, N = self.N, q = self.q))
def __eq__(self, other):
for i, (a, b) in enumerate([
(self.x, other.x), (self.y, other.y), (self.A, other.A),
(self.B, other.B), (self.N, other.N), (self.q, other.q)]):
if a != b:
return False
return True
def test():
import random
bits = 256
P = random.randrange(1 << bits) * ECPoint.std_point('secp256k1')
k = random.randrange(1 << bits)
R = k * P
found_P = modular_inverse(k, R.q) * R
assert found_P == P
print(found_P)
if __name__ == '__main__':
test()
Output:
{
'x': 108051465657467150531748691374311160382608428790397210924352716318223953013557,
'y': 4462548165448905789984443302412298811224817997977472205419179335194291964455,
'A': 0,
'B': 7,
'N': 115792089237316195423570985008687907853269984665640564039457584007908834671663,
'q': 115792089237316195423570985008687907852837564279074904382605163141518161494337
}

Resources