Constraint propagation with modulo - z3

Say I have two variables a and b. I would like to define the following relation/constraint between them:
a = 1, b % 12 = 1 or b % 12 = 0
a = 2, b % 12 = 0
Some solutions are
a = 1, b = 1
a = 1, b = 12
a = 2, b = 12
I'm currently modelling this in a straightforward way (and adding an extra condition on top):
rhs = Or(
And(a == 1, Or(b % 12 == 1, b % 12 == 0)),
And(a == 2, Or(b % 12 == 0))
)
lhs = And(b > 10)
solver.add(Implies(lhs, rhs))
However, this becomes very slow as I increase the number of variables and constraints.
Is there a better way to model this? Maybe a function? But I would like to allow search to run "in both directions", i.e. given a value of b, we should be able to identify a value of a, and vice versa.

Based on your comment, it looks like the use of integers is unnecessarily complicating your constraints.
If you need to stick to "numbers" for some other reason, then I'd recommend asserting 0 <= b and b < 12 globally (to represent all 12 notes), which can help the solver reduce the search space. However, division/modulus are always hard for SMT solvers, but perhaps you do not need them at all: In fact, I'd recommend not using numbers to represent notes in the first place. Instead use an enumeration:
Note, (A, B, C) = EnumSort('Note', ('A', 'B', 'C'))
(I've only written the first three above; you can add the remaining 9.)
This very clearly communicates to the solver that you're dealing with a finite collection of distinct items. You should also consider representing octave as some enum-type, or at least restrict it to be in some small range that covers the first 6-7 octaves which I assume you're interested in.
You can read more about enums in z3 here: https://ericpony.github.io/z3py-tutorial/advanced-examples.htm (Scroll down to the part that talks about "enumerations.")
You haven't told us how octaves/notes constrain each other in your system; but it should be easy to capture them using regular functions that take octaves and return possible notes. You should post actual code that people can run so they can see what the bottle-necks can be.

Related

Is there a way to assert that the first digit (most significant) of number is a particular digit?

I would like to assert that the most significant digit of a number is a particular value, but I don't actually know the length of the number. If it was the least significant digit, I know I could use the python mod (%) to check for it. But with an unknown number of digits, I'm unsure of how I could check this in z3.
For example, I may know that the left most digit is a 9, such as 9x, or 9xx, or 9xxx etc.
Thanks so much in advance
The generic way to do this would be to convert to a string and check that the first character matches:
from z3 import *
s = Solver()
n = Int('n')
s.add(SubString(IntToStr(n), 0, 1) == "9")
r = s.check()
if r == sat:
m = s.model()
print("n =", m[n])
else:
print("Solver said:", r)
This prints:
n = 9
Note that IntToStr expects its argument to be non-negative, so if you need to support negative numbers, you'll have to write extra code to accommodate for that. See https://smtlib.cs.uiowa.edu/theories-UnicodeStrings.shtml for details.
Aside While this will accomplish what you want in its generality, it may not be the most efficient way to encode this constraint. Since it goes through strings, the constraints generated might cause performance issues. If you have an upper limit on your number, it might be more efficient to code it explicitly. For instance, if you know your number is less than a 1000, I'd code it as (pseudocode):
n == 9 || n >= 90 && n <= 99 || n >= 900 && n <= 999
etc. until you have the range you needed covered. This would lead to much simpler constraints and perform a lot better in general. Note that this'll work even if you don't know the exact length, but have an upper bound on it. But of course, it all depends on what you are trying to achieve and what else you know about the number itself.

What is the most efficient way of checking N-way equation equivalence in Z3?

Suppose I have a set of Z3 expressions:
exprs = [A, B, C, D, E, F]
I want to check whether any of them are equivalent and, if so, determine which. The most obvious way is just an N×N comparison (assume exprs is composed of some arbitrarily-complicated boolean expressions instead of the simple numbers in the example):
from z3 import *
exprs = [IntVal(1), IntVal(2), IntVal(3), IntVal(4), IntVal(3)]
for i in range(len(exprs) - 1):
for j in range(i+1, len(exprs)):
s = Solver()
s.add(exprs[i] != exprs[j])
if unsat == s.check():
quit(f'{(i, j)} are equivalent')
Is this the most efficient method, or is there some way of quantifying over a set of arbitrary expressions? It would also be acceptable for this to be a two-step process where I first learn whether any of the expressions are equivalent, and then do a longer check to see which specific expressions are equivalent.
As with anything performance related, the answer is "it depends." Before delving into options, though, note that z3 supports Distinct, which can check whether any number of expressions are all different: https://z3prover.github.io/api/html/namespacez3py.html#a9eae89dd394c71948e36b5b01a7f3cd0
Though of course, you've a more complicated query here. I think the following two algorithms are your options:
Explicit pairwise checks
Depending on your constraints, the simplest thing to do might be to call the solver multiple times, as you alluded to. To start with, use Distinct and make a call to see if its negation is satisfiable. (i.e., check if some of these expressions can be made equal.) If the answer comes unsat, you know you can't make any equal. Otherwise, go with your loop as before till you hit the pair that can be made equal to each other.
Doing multiple checks together
You can also solve your problem using a modified algorithm, though with more complicated constraints, and hopefully faster.
To do so, create Nx(N-1)/2 booleans, one for each pair, which is equal to that pair not being equivalent. To illustrate, let's say you have the expressions A, B, and C. Create:
X0 = A != B
X1 = A != C
X2 = B != C
Now loop:
Ask if X0 || X1 || X2 is satisfiable.
If the solver comes back unsat, then all of A, B, and C are equivalent. You're done.
If the solver comes back sat, then at least one of the disjuncts X0, X1 or X2 is true. Use the model the solver gives you to determine which ones are false, and continue with those until you get unsat.
Here's a simple concrete example. Let's say the expressions are {1, 1, 2}:
Ask if 1 != 1 || 1 != 2 || 1 != 2 is sat.
It'll be sat. In the model, you'll have at least one of these disjuncts true, and it won't be the first one! In this case the last two. Drop them from your list, leaving you with 1 != 1.
Ask again if 1 != 1 is satisfiable. The answer will be unsat and you're done.
In the worst case you'll make Nx(N-1)/2 calls to the solver, if it happens that none of them can be made equivalent with you eliminating one at a time. This is where the first call to Not (Distinct(A, B, C, ...)) is important; i.e., you will start knowing that some pair is equivalent; hopefully iterating faster.
Summary
My initial hunch is that the second algorithm above will be more performant; though it really depends on what your expressions really look like. I suggest some experimentation to find out what works the best in your particular case.
A Python solution
Here's the algorithm coded:
from z3 import *
exprs = [IntVal(i) for i in [1, 2, 3, 4, 3, 2, 10, 10, 1]]
s = Solver()
bools = []
for i in range(len(exprs) - 1):
for j in range(i+1, len(exprs)):
b = Bool(f'eq_{i}_{j}')
bools.append(b)
s.add(b == (exprs[i] != exprs[j]))
# First check if they're all distinct
s.push()
s.add(Not(Distinct(*exprs)))
if(s.check()== unsat):
quit("They're all distinct")
s.pop()
while True:
# Be defensive, bools should not ever become empty here.
if not bools:
quit("This shouldn't have happened! Something is wrong.")
if s.check(Or(*bools)) == unsat:
print("Equivalent expressions:")
for b in bools:
print(f' {b}')
quit('Done')
else:
# Use the model to keep bools that are false:
m = s.model()
bools = [b for b in bools if not(m.evaluate(b, model_completion=True))]
This prints:
Equivalent expressions:
eq_0_8
eq_1_5
eq_2_4
eq_6_7
Done
which looks correct to me! Note that this should work correctly even if you have 3 (or more) items that are equivalent; of course you'll see the output one-pair at a time. So, some post-processing might be needed to clean that up, depending on the needs of the upstream algorithm.
Note that I only tested this for a few test values; there might be corner case gotchas. Please do a more thorough test and report if there're any bugs!

Genetic Algorithm timeseries forcast creating an initial population

I am building a genetic algorithm that does a time series forecast in the symbolic regression analysis. I’m trying to get the algorithm to find an equation that will match the underlying trend of the data. (predict monthly beer sales)
The idea is to use lisp like expressions, which writes the equation in a tree. This allows for branch swapping in the crossover/mating stage.
5* (5 +5)
Written as:
X = '(mul 5 (add 5 5))'
Y = parser(X)
y = ['mul', 5, ['add', 5, 5]]
I want to know how to create an initial population set where the individuals represent different expressions automatically. Where there “fitness” is related to how well each equation matches the underlying trend.
For example, one individual could be: '(add 100 (mul x (sin (mul x 3))))'
Where x is time in months.
How do I automatically generate expressions for my population? I have no idea how to do this, any help would be very appreciated.
You can easily solve this problem with recursion and a random number generator random() which returns a (pseudo-)random float between 0 and 1. Here is some pseudocode:
randomExp() {
// Choose a function(like mul or add):
func = getRandomFunction() // Just choose one of your functions randomly.
arg1 = ""
rand1 = random()
// Choose the arguments. You may choose other percentages here depending how deep you want it to be and how many 'x' you want to have.
if(rand1 < 0.2)
arg1 = randomExp() // Here add a new expression
else if(rand1 < 0.5)
arg1 = "x"
else
arg1 = randomConstant() // Get a random constant in a predefined range.
// Do the same for the second argument:
arg2 = ""
…
…
// Put everything together and return it:
return "("+func+" "+arg1+" "+arg2+")"
}
You might want to also limit the recursion depth, as this might return you a theoretically infinitely long expression.

Is there a language construct in F# for testing if a number is between two other numbers (in a range)?

I am looking for a more succinct F# equivalent of:
myNumber >= 2 && myNumber <= 4
I imagine something like
myNumber >=< (2, 4)
Is there some kind of operation like this?
There is no native operator, but you could define your own one.
let inline (>=<) a (b,c) = a >= b && a<= c
John's answer is exactly what you asked for, and the most practical solution. But this got me wondering if one could define operator(s) to enable a syntax closer to normal mathematical notation, i.e., a <= b <= c.
Here's one such solution:
let inline (<=.) left middle = (left <= middle, middle)
let inline (.<=) (leftResult, middle) right = leftResult && (middle <= right)
let inline (.<=.) middleLeft middleRight = (middleLeft .<= middleRight, middleRight)
1 <=. 3 .<=. 5 .<= 9 // true
1 <=. 10 .<= 5 // false
A few comments on this:
I used the . character to indicate the "middle" of the expression
. was a very deliberate choice, and is not easily changeable to some other character you like better (e.g. if you perhaps like the look of 1 <=# 3 #<= 5 better). The F# compiler changes the associativity and/or precedence of an operator based on the operator symbol's first character. We want standard left-to-right evaluation/short-circuiting, and . enables this.
A 3-number comparison is optimized away completely, but a 4+ number comparison results in CIL that allocates tuples and does various other business that isn't strictly necessary:
Is there some kind of operation like this?
Great question! The answer is "no", there isn't, but I wish there was.
Latkin's answer is nice, but it doesn't short-circuit evaluate. So if the first test fails the remaining subexpressions still get evaluated, even though their results are irrelevant.
FWIW, in Mathematica you can do 1<x<2 just like mathematics.

Lua base converter

I need a base converter function for Lua. I need to convert from base 10 to base 2,3,4,5,6,7,8,9,10,11...36 how can i to this?
In the string to number direction, the function tonumber() takes an optional second argument that specifies the base to use, which may range from 2 to 36 with the obvious meaning for digits in bases greater than 10.
In the number to string direction, this can be done slightly more efficiently than Nikolaus's answer by something like this:
local floor,insert = math.floor, table.insert
function basen(n,b)
n = floor(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % b) + 1
n = floor(n / b)
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,"")
end
This creates fewer garbage strings to collect by using table.concat() instead of repeated calls to the string concatenation operator ... Although it makes little practical difference for strings this small, this idiom should be learned because otherwise building a buffer in a loop with the concatenation operator will actually tend to O(n2) performance while table.concat() has been designed to do substantially better.
There is an unanswered question as to whether it is more efficient to push the digits on a stack in the table t with calls to table.insert(t,1,digit), or to append them to the end with t[#t+1]=digit, followed by a call to string.reverse() to put the digits in the right order. I'll leave the benchmarking to the student. Note that although the code I pasted here does run and appears to get correct answers, there may other opportunities to tune it further.
For example, the common case of base 10 is culled off and handled with the built in tostring() function. But similar culls can be done for bases 8 and 16 which have conversion specifiers for string.format() ("%o" and "%x", respectively).
Also, neither Nikolaus's solution nor mine handle non-integers particularly well. I emphasize that here by forcing the value n to an integer with math.floor() at the beginning.
Correctly converting a general floating point value to any base (even base 10) is fraught with subtleties, which I leave as an exercise to the reader.
you can use a loop to convert an integer into a string containting the required base. for bases below 10 use the following code, if you need a base larger than that you need to add a line that mapps the result of x % base to a character (usign an array for example)
x = 1234
r = ""
base = 8
while x > 0 do
r = "" .. (x % base ) .. r
x = math.floor(x / base)
end
print( r );

Resources