Prolog: Variable with multiple values - recursion

I'm trying to implement a program that takes a variable with multiple values and evaluates all the values. For instance:
foo(X,R) :-
X > 2,
Z is R + 1,
R = Z.
This program might not be valid, but it will help me ask the question regardless.
My question: If X has multiple values, how would I increment the counter for each value X > 2?

In order to instantiate X to increasingly larger integers you can use the following:
?- between(0, inf, X).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
<ETC.>
PS1: Notice that you have to instantiate R as well since it is used in the arithmetic expression Z is R + 1.
PS2: Notice that your program fails for all instantiations of X and R since R =\= R + 1 for finite R. The for instance means that the following query will not terminate:
?- between(0, inf, X), foo(X, 1).
Alternatively, the program can be rewritten in library CLP(FD) (created by Markus Triska):
:- use_module(library(clpfd)).
foo(X,R):-
X #> 2,
Z #= R + 1,
R #= Z.

Related

How to define Field of 16 elements in sagemath?

I'm trying to define the field with 16 elements that is F_2(x) modulus x^4+x+1.
I mean, the elements are polynomials with coefficient 1 or 0 and a base is {x^³, x^2, x, 1}.
Then, I need to define matrixes with elements of this field and be abble to multiply them as usual.
I'm trying to to do this in sagemath since it is supposed to be easier.
How can this be done?
I've tried
F.<xi>=GF(2^4, modulus=GF(2)[x](x^4+x+1))
but it doesn't work.
First make sure that x or some other letter used in the optional parameter modulus=... is a generator of a polynomial ring over the field with two elements, GF(2). I will use X but any other letter would do instead. Then just use it.
R.<X> = PolynomialRing(GF(2))
F.<a> = GF(2^4, modulus=X^4 + X + 1)
print(f'F is {F}')
print(f'a has minimal polynomial {a.minpoly()}')
Results:
F is Finite Field in a of size 2^4
a has minimal polynomial x^4 + x + 1
Let us multiply some simple matrices defined over this field.
A = matrix(2, 2, [1, a, a, a^2])
B = matrix(2, 2, [1, a, a, a^3])
AB = A*B
print(f'AB is the matrix\n{AB}')
This gives:
AB is the matrix
[a^2 + 1 1]
[a^3 + a a]

User-defined (nonlinear) objective with vectorized variables in JuMP

Is it possible to use vectorized variables with user-defined objective functions in JuMP for Julia? Like so,
model = Model(GLPK.Optimizer)
A = [
1 1 9 5
3 5 0 8
2 0 6 13
]
b = [7; 3; 5]
c = [1; 3; 5; 2]
#variable(model, x[1:4] >= 0)
#constraint(model, A * x .== b)
# dummy functions, could be nonlinear hypothetically
identity(x) = x
C(x, c) = c' * x
register(model, :identity, 1, identity; autodiff = true)
register(model, :C, 2, C; autodiff = true)
#NLobjective(model, Min, C(identity(x), c))
This throws the error,
ERROR: Unexpected array VariableRef[x[1], x[2], x[3], x[4]] in nonlinear expression. Nonlinear expressions may contain only scalar expression.
Which sounds like no. Is there a workaround to this? I believe scipy.optimize.minimize is capable of optimizing user-defined objectives with vectorized variables?
No, you cannot pass vector arguments to user-defined functions.
Documentation: https://jump.dev/JuMP.jl/stable/manual/nlp/#User-defined-functions-with-vector-inputs
Issue you opened: https://github.com/jump-dev/JuMP.jl/issues/2854
The following is preferable to Prezemyslaw's answer. His suggestion to wrap things in an #expression won't work if the functions are more complicated.
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
A = [
1 1 9 5
3 5 0 8
2 0 6 13
]
b = [7; 3; 5]
c = [1; 3; 5; 2]
#variable(model, x[1:4] >= 0)
#constraint(model, A * x .== b)
# dummy functions, could be nonlinear hypothetically
identity(x) = x
C(x, c) = c' * x
my_objective(x...) = C(identitiy(collect(x)), c)
register(model, :my_objective, length(x), my_objective; autodiff = true)
#NLobjective(model, Min, my_objective(x...))
Firstly, use optimizer that supports nonlinear models. GLPK does not. Try Ipopt:
using Ipopt
model = Model(Ipopt.Optimizer)
Secondly, JuMP documentation reads (see https://jump.dev/JuMP.jl/stable/manual/nlp/#Syntax-notes):
The syntax accepted in nonlinear macros is more restricted than the syntax for linear and quadratic macros. (...) all expressions must be simple scalar operations. You cannot use dot, matrix-vector products, vector slices, etc.
you need wrap the goal function
#expression(model, expr, C(identity(x), c))
Now you can do:
#NLobjective(model, Min, expr)
To show that it works I solve the model:
julia> optimize!(model)
This is Ipopt version 3.14.4, running with linear solver MUMPS 5.4.1.
...
Total seconds in IPOPT = 0.165
EXIT: Optimal Solution Found.
julia> value.(x)
4-element Vector{Float64}:
0.42307697548737005
0.3461538282496562
0.6923076931757742
-8.46379887234798e-9

Concatenation of binary representation of first n positive integers in O(logn) time complexity

I came across this question in a coding competition. Given a number n, concatenate the binary representation of first n positive integers and return the decimal value of the resultant number formed. Since the answer can be large return answer modulo 10^9+7.
N can be as large as 10^9.
Eg:- n=4. Number formed=11011100(1=1,10=2,11=3,100=4). Decimal value of 11011100=220.
I found a stack overflow answer to this question but the problem is that it only contains a O(n) solution.
Link:- concatenate binary of first N integers and return decimal value
Since n can be up to 10^9 we need to come up with solution that is better than O(n).
Here's some Python code that provides a fast solution; it uses the same ideas as in Abhinav Mathur's post. It requires Python >= 3.8, but it doesn't use anything particularly fancy from Python, and could easily be translated into another language. You'd need to write algorithms for modular exponentiation and modular inverse if they're not already available in the target language.
First, for testing purposes, let's define the slow and obvious version:
# Modulus that results are reduced by,
M = 10 ** 9 + 7
def slow_binary_concat(n):
"""
Concatenate binary representations of 1 through n (inclusive).
Reinterpret the resulting binary string as an integer.
"""
concatenation = "".join(format(k, "b") for k in range(n + 1))
return int(concatenation, 2) % M
Checking that we get the expected result:
>>> slow_binary_concat(4)
220
>>> slow_binary_concat(10)
462911642
Now we'll write a faster version. First, we split the range [1, n) into subintervals such that within each subinterval, all numbers have the same length in binary. For example, the range [1, 10) would be split into four subintervals: [1, 2), [2, 4), [4, 8) and [8, 10). Here's a function to do that splitting:
def split_by_bit_length(n):
"""
Split the numbers in [1, n) by bit-length.
Produces triples (a, b, 2**k). Each triple represents a subinterval
[a, b) of [1, n), with a < b, all of whose elements has bit-length k.
"""
a = 1
while n > a:
b = 2 * a
yield (a, min(n, b), b)
a = b
Example output:
>>> list(split_by_bit_length(10))
[(1, 2, 2), (2, 4, 4), (4, 8, 8), (8, 10, 16)]
Now for each subinterval, the value of the concatenation of all numbers in that subinterval is represented by a fairly simple mathematical sum, which can be computed in exact form. Here's a function to compute that sum modulo M:
def subinterval_concat(a, b, l):
"""
Concatenation of values in [a, b), all of which have the same bit-length k.
l is 2**k.
Equivalently, sum(i * l**(b - 1 - i)) for i in range(a, b)) modulo M.
"""
n = b - a
inv = pow(l - 1, -1, M)
q = (pow(l, n, M) - 1) * inv
return (a * q + (q - n) * inv) % M
I won't go into the evaluation of the sum here: it's a bit off-topic for this site, and it's hard to express without a good way to render formulas. If you want the details, that's a topic for https://math.stackexchange.com, or a page of fairly simple algebra.
Finally, we want to put all the intervals together. Here's a function to do that.
def fast_binary_concat(n):
"""
Fast version of slow_binary_concat.
"""
acc = 0
for a, b, l in split_by_bit_length(n + 1):
acc = (acc * pow(l, b - a, M) + subinterval_concat(a, b, l)) % M
return acc
A comparison with the slow version shows that we get the same results:
>>> fast_binary_concat(4)
220
>>> fast_binary_concat(10)
462911642
But the fast version can easily be evaluated for much larger inputs, where using the slow version would be infeasible:
>>> fast_binary_concat(10**9)
827129560
>>> fast_binary_concat(10**18)
945204784
You just have to note a simple pattern. Taking up your example for n=4, let's gradually build the solution starting from n=1.
1 -> 1 #1
2 -> 2^2(1) + 2 #6
3 -> 2^2[2^2(1)+2] + 3 #27
4 -> 2^3{2^2[2^2(1)+2]+3} + 4 #220
If you expand the coefficients of each term for n=4, you'll get the coefficients as:
1 -> (2^3)*(2^2)*(2^2)
2 -> (2^3)*(2^2)
3 -> (2^3)
4 -> (2^0)
Let the N be total number of bits in the string representation of our required number, and D(x) be the number of bits in x. The coefficients can then be written as
1 -> 2^(N-D(1))
2 -> 2^(N-D(1)-D(2))
3 -> 2^(N-D(1)-D(2)-D(3))
... and so on
Since the value of D(x) will be the same for all x between range (2^t, 2^(t+1)-1) for some given t, you can break the problem into such ranges and solve for each range using mathematics (not iteration). Since the number of such ranges will be log2(Given N), this should work in the given time limit.
As an example, the various ranges become:
1. 1 (D(x) = 1)
2. 2-3 (D(x) = 2)
3. 4-7 (D(x) = 3)
4. 8-15 (D(x) = 4)

"Syntax error" while writing OCaml function?

I am writing a function in OCaml to raise x to the power of y.
My code is:
#let rec pow x y =
if y == 0 then 1 else
if (y mod 2 = 0) then pow x y/2 * pow x y/2 else
x * pow x y/2 * pow x y/2;;
When I try to execute it, I get an error for syntax in line one, but it doesn't tell me what it is.
When you wrote the code, did you type the #? The # is just a character that the OCaml REPL outputs to prompt for input; it is not part of the code. You should not type it.
Here are some other errors that you should fix:
== is physical equality in OCaml. = is structural equality. Although both work the same for unboxed types (such as int), it's better practice to do y = 0. Note that you use =, the recommended equality, in the expression y mod 2 = 0.
You need parentheses around y/2. pow x y/2 parses as (pow x y) / 2, but you want pow x (y / 2).

Prolog:: f(x) recursion

I'm a beginner to Prolog and have two requirements:
f(1) = 1
f(x) = 5x + x^2 + f(x - 1)
rules:
f(1,1).
f(X,Y) :-
Y is 5 * X + X * X + f(X-1,Y).
query:
f(4,X).
Output:
ERROR: is/2: Arguments are not sufficiently instantiated
How can I add value of f(X-1)?
This can be easily solved by using auxiliary variables.
For example, consider:
f(1, 1).
f(X, Y) :-
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
This is a straight-forward translation of the rules you give, using auxiliary variables T1 and T2 which stand for the partial expressions f(X-1) and X-1, respectively. As #BallpointBen correctly notes, it is not sufficient to use the terms themselves, because these terms are different from their arithmetic evaluation. In particular, -(2,1) is not the integer 1, but 2 - 1 #= 1 does hold!
Depending on your Prolog system, you may ned to currently still import a library to use the predicate (#=)/2, which expresses equality of integer expressesions.
Your example query now already yields a solution:
?- f(4, X).
X = 75 .
Note that the predicate does not terminate universally in this case:
?- f(4, X), false.
nontermination
We can easily make it so with an additional constraint:
f(1, 1).
f(X, Y) :-
X #> 1,
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
Now we have:
?- f(4, X).
X = 75 ;
false.
Note that we can use this as a true relation, also in the most general case:
?- f(X, Y).
X = Y, Y = 1 ;
X = 2,
Y = 15 ;
X = 3,
Y = 39 ;
X = 4,
Y = 75 ;
etc.
Versions based on lower-level arithmetic typically only cover a very limited subset of instances of such queries. I therefore recommend that you use (#=)/2 instead of (is)/2. Especially for beginners, using (is)/2 is too hard to understand. Take the many related questions filed under instantiation-error as evidence, and see clpfd for declarative solutions.
The issue is that you are trying to evaluate f(X-1,Y) as if it were a number, but of course it is a predicate that may be true or false. After some tinkering, I found this solution:
f(1,1).
f(X,Y) :- X > 0, Z is X-1, f(Z,N), Y is 5*X + X*X + N.
The trick is to let it find its way down to f(1,N) first, without evaluating anything; then let the results bubble back up by satisfying Y is 5*X + X*X + N. In Prolog, order matters for its search. It needs to satisfy f(Z,N) in order to have a value of N for the statement Y is 5*X + X*X + N.
Also, note the condition X > 0 to avoid infinite recursion.

Resources