Is there a way to use range with Z3ints in z3py? - z3py

I'm relatively new to Z3 and experimenting with it in python. I've coded a program which returns the order in which different actions is performed, represented with a number. Z3 returns an integer representing the second the action starts.
Now I want to look at the model and see if there is an instance of time where nothing happens. To do this I made a list with only 0's and I want to change the index at the times where each action is being executed, to 1. For instance, if an action start at the 5th second and takes 8 seconds to be executed, the index 5 to 12 would be set to 1. Doing this with all the actions and then look for 0's in the list would hopefully give me the instances where nothing happens.
The problem is: I would like to write something like this for coding the problem
list_for_check = [0]*total_time
m = s.model()
for action in actions:
for index in range(m.evaluate(action.number) , m.evaluate(action.number) + action.time_it_takes):
list_for_check[index] = 1
But I get the error:
'IntNumRef' object cannot be interpreted as an integer
I've understood that Z3 isn't returning normal ints or bools in their models, but writing
if m.evaluate(action.boolean):
works, so I'm assuming the if is overwritten in a way, but this doesn't seem to be the case with range. So my question is: Is there a way to use range with Z3 ints? Or is there another way to do this?
The problem might also be that action.time_it_takes is an integer and adding a Z3int with a "normal" int doesn't work. (Done in the second part of the range).
I've also tried using int(m.evaluate(action.number)), but it doesn't work.
Thanks in advance :)

When you call evaluate it returns an IntNumRef, which is an internal z3 representation of an integer number inside z3. You need to call as_long() method of it to convert it to a Python number. Here's an example:
from z3 import *
s = Solver()
a = Int('a')
s.add(a > 4);
s.add(a < 7);
if s.check() == sat:
m = s.model()
print("a is %s" % m.evaluate(a))
print("Iterating from a to a+5:")
av = m.evaluate(a).as_long()
for index in range(av, av + 5):
print(index)
When I run this, I get:
a is 5
Iterating from a to a+5:
5
6
7
8
9
which is exactly what you're trying to achieve.
The method as_long() is defined here. Note that there are similar conversion functions from bit-vectors and rationals as well. You can search the z3py api using the interface at: https://z3prover.github.io/api/html/namespacez3py.html

Related

How do I repeat a random number

I've tried searching for help but I haven't found a solution yet, I'm trying to repeat math.random.
current code:
local ok = ""
for i = 0,10 do
local ok = ok..math.random(0,10)
end
print(ok)
no clue why it doesn't work, please help
Long answer
Even if the preferable answer is already given, just copying it will probably not lead to the solution you may expect or less future mistakes. So I decided to explain why your code fails and to fix it and also help better understand how DarkWiiPlayer's answer works (except for string.rep and string.gsub).
Issues
There are at least three issues in your code:
the math.random(m, n) function includes lower and the upper values
local declarations hide a same-name objects in outer scopes
math.random gives the same number sequence unless you set its seed with math.randomseed
See Detailed explanation section below for more.
Another point seems at least worth mentioning or suspicious to me, as I assume you might be puzzled by the result (it seems to me to reflect exactly the perspective of the C programmer, from which I also got to know Lua): the Lua for loop specifies start and end value, so both of these values are included.
Attempt to repair
Here I show how a version of your code that yields the same results as the answer you accepted: a sequence of 10 percent-encoded decimal digits.
-- this will change the seed value (but mind that its resolution is seconds)
math.randomseed(os.time())
-- initiate the (only) local variable we are working on later
local ok = ""
-- encode 10 random decimals (Lua's for-loop is one-based and inclusive)
for i = 1, 10 do
ok = ok ..
-- add fixed part
'%3' ..
-- concatenation operator implicitly converts number to string
math.random(0, 9) -- a random number in range [0..9]
end
print(ok)
Detailed explanation
This explanation makes heavily use of the assert function instead of adding print calls or comment what the output should be. In my opinion assert is the superior choice for illustrating expected behavior: The function guides us from one true statement - assert(true) - to the next, at the first miss - assert(false) - the program is exited.
Random ranges
The math library in Lua provides actually three random functions depending on the count of arguments you pass to it. Without arguments, the result is in the interval [0,1):
assert(math.random() >= 0)
assert(math.random() < 1)
the one-argument version returns a value between 1 and the argument:
assert(math.random(1) == 1)
assert(math.random(10) >= 1)
assert(math.random(10) <= 10)
the two-argument version explicitly specifies min and max values:
assert(math.random(2,2) == 2)
assert(math.random(0, 9) >= 0)
assert(math.random(0, 9) <= 9)
Hidden outer variable
In this example, we have two variables x of different type, the outer x is not accessible from the inner scope.
local x = ''
assert(type(x) == 'string')
do
local x = 0
assert(type(x) == 'number')
-- inner x changes type
x = x .. x
assert(x == '00')
end
assert(type(x) == 'string')
Predictable randomness
The first call to math.random() in a Lua program will return always the same number because the pseudorandom number generator (PRNG) starts at seed 1. So if you call math.randomseed(1), you'll reset the PRNG to its initial state.
r0 = math.random()
math.randomseed(1)
r1 = math.random()
assert(r0 == r1)
After calling math.randomseed(os.time()) calls to math.random() will return different sequences presuming that subsequent program starts differ at least by one second. See question Current time in milliseconds and its answers for more information about the resolutions of several Lua functions.
string.rep(".", 10):gsub(".", function() return "%3" .. math.random(0, 9) end)
That should give you what you want

Input to different attributes values from a random.sample list

so this is what I'm trying to do, and I'm not sure how cause I'm new to python. I've searched for a few options and I'm not sure why this doesn't work.
So I have 6 different nodes, in maya, called aiSwitch. I need to generate random different numbers from 0 to 6 and input that value in the aiSiwtch*.index.
In short the result should be
aiSwitch1.index = (random number from 0 to 5)
aiSwitch2.index = (another random number from 0 to 5 different than the one before)
And so on unil aiSwitch6.index
I tried the following:
import maya.cmds as mc
import random
allswtich = mc.ls('aiSwitch*')
for i in allswitch:
print i
S = range(0,6)
print S
shuffle = random.sample(S, len(S))
print shuffle
for w in shuffle:
print w
mc.setAttr(i + '.index', w)
This is the result I get from the prints:
aiSwitch1 <-- from print i
[0,1,2,3,4,5] <--- from print S
[2,3,5,4,0,1] <--- from print Shuffle (random.sample results)
2
3
5
4
0
1 <--- from print w, every separated item in the random.sample list.
Now, this happens for every aiSwitch, cause it's in a loop of course. And the random numbers are always a different list cause it happens every time the loop runs.
So where is the problem then?
aiSwitch1.index = 1
And all the other aiSwitch*.index always take only the last item in the list but the time I get to do the setAttr. It seems to be that w is retaining the last value of the for loop. I don't quite understand how to
Get a random value from 0 to 5
Input that value in aiSwitch1.index
Get another random value from 0 to 6 different to the one before
Input that value in aiSwitch2.index
Repeat until aiSwitch5.index.
I did get it to work with the following form:
allSwitch = mc.ls('aiSwitch')
for i in allSwitch:
mc.setAttr(i + '.index', random.uniform(0,5))
This gave a random number from 0 to 5 to all aiSwitch*.index, but some of them repeat. I think this works cause the value is being generated every time the loop runs, hence setting the attribute with a random number. But the numbers repeat and I was trying to avoid that. I also tried a shuffle but failed to get any values from it.
My main mistake seems to be that I'm generating a list and sampling it, but I'm failing to assign every different item from that list to different aiSwitch*.index nodes. And I'm running out of ideas for this.
Any clues would be greatly appreciated.
Thanks.
Jonathan.
Here is a somewhat Pythonic way: shuffle the list of indices, then iterate over it using zip (which is useful for iterating over structures in parallel, which is what you need to do here):
import random
index = list(range(6))
random.shuffle(index)
allSwitch = mc.ls('aiSwitch*')
for i,j in zip(allSwitch,index):
mc.setAttr(i + '.index', j)

Assignment problems with simple random number generation in Modelica

I am relatively new to Modelica (Dymola-environment) and I am getting very desperate/upset that I cannot solve such a simple problem as a random number generation in Modelica and I hope that you can help me out.
The simple function random produces a random number between 0 and 1 with an input seed seedIn[3] and produces the output seed seedOut[3] for the next time step or event. The call
(z,seedOut) = random(seedIn);
works perfectly fine.
The problem is that I cannot find a way in Modelica to compute this assignment over time by using the seedOut[3] as the next seedIn[3], which is very frustrating.
My simple program looks like this:
*model Randomgenerator
Real z;
Integer seedIn[3]( start={1,23,131},fixed=true), seedOut[3];
equation
(z,seedOut) = random(seedIn);
algorithm
seedIn := seedOut;
end Randomgenerator;*
I have tried nearly all possibilities with algorithm assignments, initial conditions and equations but none of them works. I just simply want to use seedOut in the next time step. One problem seems to be that when entering into the algorithm section, neither the initial conditions nor the values from the equation section are used.
Using the 'sample' and 'reinit' functions the code below will calculate a new random number at the frequency specified in 'sample'. Note the way of defining the "start value" of seedIn.
model Randomgenerator
Real seedIn[3] = {1,23,131};
Real z;
Real[3] seedOut;
equation
(z,seedOut) = random(seedIn);
when sample(1,1) then
reinit(seedIn,pre(seedOut));
end when;
end Randomgenerator;
The 'pre' function allows the use of the previous value of the variable. If this was not used, the output 'z' would have returned a constant value. Two things regarding the 'reinint' function, it requires use of 'when' and requires 'Real' variables/expressions hence seedIn and seedOut are now defined as 'Real'.
The simple "random" generator I used was:
function random
input Real[3] seedIn;
output Real z;
output Real[3] seedOut;
algorithm
seedOut[1] :=seedIn[1] + 1;
seedOut[2] :=seedIn[2] + 5;
seedOut[3] :=seedIn[3] + 10;
z :=(0.1*seedIn[1] + 0.2*seedIn[2] + 0.3*seedIn[3])/(0.5*sum(seedIn));
end random;
Surely there are other ways depending on the application to perform this operation. At least this will give you something to start with. Hope it helps.

numerical recipies ran3 generates negative numbers

I am using numerical recipes scheme to generate random numbers (ran3, page 7 in this PDF file). I didn't notice anything strange but this time, I got a negative numbers at the "warm up" stage which are larger than MBIG. The code look as if this shouldn't happen. I can easily fix this with changing the if statement to be a while statement at the line that says if(mk.lt.MZ)mk=mk+MBIG but I want to know what are the consequences.
Edit:here is the function
FUNCTION ran3a(idum)
INTEGER idum
INTEGER MBIG,MSEED,MZ
C REAL MBIG,MSEED,MZ
REAL ran3a,FAC
PARAMETER (MBIG=1000000000,MSEED=161803398,MZ=0,FAC=1./MBIG)
C PARAMETER (MBIG=4000000.,MSEED=1618033.,MZ=0.,FAC=1./MBIG)
INTEGER i,iff,ii,inext,inextp,k
INTEGER mj,mk,ma(55)
C REAL mj,mk,ma(55)
SAVE iff,inext,inextp,ma
DATA iff /0/
if(idum.lt.0.or.iff.eq.0)then
iff=1
mj=MSEED-iabs(idum)
mj=mod(mj,MBIG)
ma(55)=mj
mk=1
do 11 i=1,54
ii=mod(21*i,55)
ma(ii)=mk
mk=mj-mk
if(mk.lt.MZ)mk=mk+MBIG
mj=ma(ii)
11 continue
do 13 k=1,4
do 12 i=1,55
ma(i)=ma(i)-ma(1+mod(i+30,55))
if(ma(i).lt.MZ)ma(i)=ma(i)+MBIG
12 continue
13 continue
inext=0
inextp=31
idum=1
endif
inext=inext+1
if(inext.eq.56)inext=1
inextp=inextp+1
if(inextp.eq.56)inextp=1
mj=ma(inext)-ma(inextp)
if(mj.lt.MZ)mj=mj+MBIG
ma(inext)=mj
ran3a=mj*FAC
return
END
I was getting Seg Faults (using gfortran 4.8) because the function was trying to change the input value idum from the negative number to 1. There is no reason for that line (nor anything with iff), so I deleted it and printed out the array ma at several different places and found no negative numbers in the array.
One possibility, though, is if iabs(idum) is larger than MSEED, you might have a problem with the line mj=MSEED - iabs(idum). You should protect from this by using mj=abs(MSEED-abs(idum)) like the book has written.
Had a look at the pdf. What you need to do is
1) Seed it: value = ran3(-1)
2) Use it: value = ran3(0)

simple method to keep last n elements in a queue for vb6?

I am trying to keep the last n elements from a changing list of x elements (where x >> n)
I found out about the deque method, with a fixed length, in other programming languages. I was wondering if there is something similar for VB6
Create a Class that extends an encapsulated Collection.
Add at the end (anonymous), retrieve & remove from the beginning (index 1). As part of adding check your MaxDepth property setting (or hard code it if you like) and if Collection.Count exceeds it remove the extra item.
Or just hard code it all inline if a Class is a stumper for you.
This is pretty routine.
The only thing I can think of is possibly looping through the last 5 values of the dynamic array using something like:
For UBound(Array) - 5 To UBound(Array)
'Code to store or do the desired with these values
Loop
Sorry I don't have a definite answer, but hopefully that might help.
Here's my simplest solution to this:
For i = n - 1 To 1 Step -1
arrayX(i) = arrayX(i - 1)
Next i
arrayX(0) = latestX
Where:
arrayX = array of values
n = # of array elements
latestX = latest value of interest (assumes entire code block is also
within another loop)

Resources