Some questions about writing 2D array with assignment and stack - tla+

I'm now writing a spec which needs a 2D array and a stack,
and I need to assign the 2D array with some values in initial state,
also give this 2D array a range of possible values in typeinvariant,
like a function.
So I write some part of my spec like this because I don't know how to assign 2D array in initial state ,
in which variable predict_table is the 2D array :
TypeInvariant == /\ stack \in Seq(all_syntax_symbol)
/\ token_pointer \in 1..Len(input_token)+1
/\ predict_table \in [ grammar_symbol_set -> [ terminal_symbol_set -> Seq(all_syntax_symbol)]]
/\ parsing_status \in 0..3
 
Init == /\ stack = <<13,-1>>
/\ token_pointer = 1
/\ predict_table = [x \in grammar_symbol_set,y \in terminal_symbol_set |-> <<>>]
/\ parsing_status = 0
Action_1 == /\ parsing_status = 0
/\ parsing_status' = 1
/\ predict_table' = [predict_table EXCEPT ![-1][12] = <<-9,-3,-2>>,![-2][12] = <<11,4,12>>,![-3][4]= <<-4,10,4>>,![-4][7]= <<-7>>,![-4][8]= <<-6>>,![-4][9]= <<-5>>,![-5][9]= <<-8,-8,9>>,![-6][8]= <<-8,-8,8>>,![-7][7]= <<-8,-8,7>>,![-8][4]= <<4>>,![-8][6]= <<5,-4,6>>,![-9][3]= <<1,-10,-3,2,3>>,![-10][7]= <<-7>>,![-10][8]= <<-6>>,![-10][9]= <<-5>>]
/\ UNCHANGED <<stack,token_pointer>>
However TLC told me that the way I assign in init(and maybe in Action_1?) and make it invariant in TypeInvariant is not OK.
And I don't know how to make it correct.
================================================================
Another question is about push and pop action of stack in my spec.
I write them in this way,in which variable stack just means my FILO stack:
Action_2 == /\ parsing_status = 1
/\ (stack[Len(stack)] = input_token[token_pointer]) /\ (stack[Len(stack)] \in terminal_symbol_set)
/\ stack' = IF Len(stack)>1 THEN SubSeq(stack,1,Len(stack)-1) ELSE <<>>
/\ parsing_status' = IF Len(stack) = 1 THEN 3 ELSE 1
/\ token_pointer' = token_pointer+1
/\ UNCHANGED <<predict_table>>
Action_5 == /\ parsing_status = 1
/\ (predict_table[stack[Len(stack)]][input_token[token_pointer]] # <<>>) /\ (predict_table[stack[Len(stack)]][input_token[token_pointer]] # <<0>>)
/\ stack' = IF Len(stack)>1 THEN SubSeq(stack,1,Len(stack)-1) \o predict_table[stack[Len(stack)]][input_token[token_pointer]] ELSE predict_table[stack[Len(stack)]][input_token[token_pointer]]
/\ UNCHANGED <<parsing_status,token_pointer,predict_table>>
I wonder whether the pop action in Action_2 and push action in Action_5 of my stack is good in functionality.
================================================================
And here is my full spec,
imitating the predictive parsing algorithm,
while the grammar making up the predict table is in LL(1).
I wonder if there're more TLA+ syntax errors in it
, and it'd be grateful if you could tell me:
----------------------------- MODULE Parser_DFA -----------------------------
EXTENDS Integers,Naturals,Reals,Sequences
CONSTANTS input_token
VARIABLES stack,token_pointer,predict_table,parsing_status
vars == <<stack,token_pointer,predict_table,parsing_status>>
grammar_symbol_set == -10..-1
\* non-terminal symbol set
terminal_symbol_set == 1..13
\* terminal symbol set, 13 stands for EOF($)
all_syntax_symbol == grammar_symbol_set \union terminal_symbol_set \union {0}
\* 0 stands for epslion( ε )
TypeInvariant == /\ stack \in Seq(all_syntax_symbol)
/\ token_pointer \in 1..Len(input_token)+1
/\ predict_table \in [ grammar_symbol_set -> [ terminal_symbol_set -> Seq(all_syntax_symbol)]]
/\ parsing_status \in 0..3
 
Init == /\ stack = <<13,-1>>
/\ token_pointer = 1
/\ predict_table = [x \in grammar_symbol_set,y \in terminal_symbol_set |-> <<>>]
/\ parsing_status = 0
\*init state of predictive parsing
Action_1 == /\ parsing_status = 0
/\ parsing_status' = 1
/\ predict_table' = [predict_table EXCEPT ![-1][12] = <<-9,-3,-2>>,![-2][12] = <<11,4,12>>,![-3][4]= <<-4,10,4>>,![-4][7]= <<-7>>,![-4][8]= <<-6>>,![-4][9]= <<-5>>,![-5][9]= <<-8,-8,9>>,![-6][8]= <<-8,-8,8>>,![-7][7]= <<-8,-8,7>>,![-8][4]= <<4>>,![-8][6]= <<5,-4,6>>,![-9][3]= <<1,-10,-3,2,3>>,![-10][7]= <<-7>>,![-10][8]= <<-6>>,![-10][9]= <<-5>>]
/\ UNCHANGED <<stack,token_pointer>>
\*still init state of predictive parsing,but for predictive table assignment.
Action_2 == /\ parsing_status = 1
/\ (stack[Len(stack)] = input_token[token_pointer]) /\ (stack[Len(stack)] \in terminal_symbol_set)
/\ stack' = IF Len(stack)>1 THEN SubSeq(stack,1,Len(stack)-1) ELSE <<>>
/\ parsing_status' = IF Len(stack) = 1 THEN 3 ELSE 1
/\ token_pointer' = token_pointer+1
/\ UNCHANGED <<predict_table>>
\* detects a terminal symbol and matchs in input_token and stack,pop and pointer++
 \* parsing_status = 1 means OK, 2 means error, 3 means finished without error
Action_2_null == /\ parsing_status = 1
/\ predict_table[stack[Len(stack)]][input_token[token_pointer]] = <<0>>
/\ stack' = IF Len(stack)>1 THEN SubSeq(stack,1,Len(stack)-1) ELSE <<>>
/\ parsing_status' = IF Len(stack) = 1 THEN 3 ELSE 1
/\ UNCHANGED <<parsing_status,predict_table>>
\* detects a epslion( ε ) in predictive table, just pop in stack is OK
Action_3 == /\ parsing_status = 1
/\ stack[Len(stack)] \in terminal_symbol_set
/\ stack[Len(stack)] # input_token[token_pointer]
/\ parsing_status' = 2
/\ UNCHANGED <<stack,token_pointer,predict_table>>
\* detects a terminal symbol and not match in input_token and stack, means error.
Action_4 == /\ parsing_status = 1
/\ predict_table[stack[Len(stack)]][input_token[token_pointer]] = <<>>
/\ parsing_status' = 2
/\ UNCHANGED <<stack,token_pointer,predict_table>>
\* parsing error(predictive table of this pair of symbol is empty)
Action_5 == /\ parsing_status = 1
/\ (predict_table[stack[Len(stack)]][input_token[token_pointer]] # <<>>) /\ (predict_table[stack[Len(stack)]][input_token[token_pointer]] # <<0>>)
/\ stack' = IF Len(stack)>1 THEN SubSeq(stack,1,Len(stack)-1) \o predict_table[stack[Len(stack)]][input_token[token_pointer]] ELSE predict_table[stack[Len(stack)]][input_token[token_pointer]]
/\ UNCHANGED <<parsing_status,token_pointer,predict_table>>
\* detects a non-terminal symbol and update the stack.
Next == Action_1 \/ Action_2 \/ Action_2_null \/ Action_3 \/ Action_4 \/ Action_5
Spec == Init /\ [][Next]_vars
Invariant_1 == parsing_status = 3 => token_pointer = Len(input_token)
\*means parsing finished
Invariant_2 == parsing_status = 2 => Len(stack) # 0
\*means parsing error and not finished
=============================================================================
Thank you for your reading.
I know it's quite long but this's the best I can describe my question.
I'm sorry for that.

Related

Python - global variable inside a while loop

I have this code, where:
last_price - is a variable that gets data from a price feed.
the code, does not work as intended. it shows this output "2 test line Y", but it should show 'test line success Y'
EDIT: I cannot use "continue", because last_price is changing every second, and (Y = 'test line Y') will become (Y = 'some other command') and the code will continue execute order_succeeded_1 indefinitely.
How can I fix this code?
last_price = 230
SL = 100
SL1 = 200
SL2 = 300
SL3 = 400
X = 'yes X'
Y = 'yes Y'
Z = 'yes Z'
def addvar (A, B):
while True:
global X, Y, Z
if X == 'test line X':
print ('test line success X')
break
if Y == 'test line Y':
print ('test line success Y')
break
if Z == 'test line Z':
print ('test line success Z')
break
if SL < last_price <= SL1 : # 100 --- 200
order_succeeded = A+B # 10
X = 'test line X'
print (order_succeeded, X)
break
if SL1 < last_price <= SL2 : # 200 --- 300
order_succeeded_1 = A-B # 2
Y = 'test line Y'
print (order_succeeded_1, Y)
break
if SL2 < last_price <= SL3 : # 300 --- 400
Z = 'test line Z'
order_succeeded_2 = A * B # 24
print (order_succeeded_2, Z)
break
addvar (6, 4)
You need to use continue instead of break here, when you use break you get out of your while and Y == 'test line Y' is not executed for the second time:
if SL1 < last_price <= SL2: # 200 --- 300
order_succeeded_1 = A - B # 2
Y = 'test line Y'
print(order_succeeded_1, Y)
continue

Why doesn't assigning new values to a numpy array work?

I have the following code. The beggining is quite long, but only serves to generate data. The problem happens with a few lines at the end.
##### Import packages
import numpy as np
import scipy.linalg as la
##### Initial conditions
N = 5
lamda = 7
mu = 2
a = 0.5
r = - np.log(a).copy()
St_Sp = np.arange(- N, N + 1)
Card = St_Sp.shape[0]
##### Define infintesimal generator
def LL(x, y):
if x == N or x == - N: re = 0
elif x - y == - 1: re = lamda
elif x - y == 1: re = mu
elif x - y == 0: re = - (mu + lamda)
else: re = 0
return re
def L(x):
return - LL(x, x)
##### Define function Phi
def Phi(x): return max(x, 0)
Phi = np.vectorize(Phi)
##### Define vector b
b = Phi(St_Sp).copy()
##### Define function Psi
def Psi(x): return L(x) / (L(x) + r)
Psi = np.vectorize(Psi)
##### Generate a Boolean vector whose all elements are False
d = np.array([0] * Card).astype(bool)
##### Define matrix A
A = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if (i != j) & (L(St_Sp[i]) != 0):
A[i, j] = LL(St_Sp[i], St_Sp[j]) / L(St_Sp[i])
elif (i != j) & (L(St_Sp[i]) == 0):
A[i, j] = 0
elif (i == j) & (Psi(St_Sp[i]) != 0):
A[i, j] = - 1 / Psi(St_Sp[i])
else: A[i, j] = 1
##### Row names of A
rows = np.arange(0, Card)
##### Define matrix B
B = np.zeros((Card, Card))
for i in range(Card):
for j in range(Card):
if i != j:
B[i, j] = LL(St_Sp[i], St_Sp[j])
else: B[i, j] = LL(St_Sp[i], St_Sp[j]) - r
##### Generate I_0
I = [np.array([1] * Card).astype(bool), d.copy()]
Z = b.copy()
index0 = np.matmul(B, Z) <= 0
index1 = ~ index0
##### Generate I_1
I = [index0, index1]
Z = b.copy()
if np.sum(I[1]) > 0:
order = np.concatenate((rows[I[1]], rows[~ I[1]]))
A1 = A[np.ix_(rows[I[1]], order)]
A2 = la.lu(A1)[2]
p = np.atleast_2d(A1).shape[0]
B1 = A2[:, range(p)]
B2 = - np.matmul(A2[:, p:], Z[I[0]])
print('Before being assigned new values, Z is \n', Z)
print('\n The index I[1] of elements of Z to be change \n', I[1])
M = la.solve_triangular(B1, B2, lower = False)
print('\n The values to be assigned to Z[I[1]] is \n', M)
Z[I[1]] = M
print('\n After being assigned new values, Z is \n', Z)
with result
Before being assigned new values, Z is
[0 0 0 0 0 0 1 2 3 4 5]
The index I[1] of elements of Z to be change
[False False False False False True True True True True False]
The values to be assigned to Z[I[1]] is
[2.08686055 2.88974949 3.40529229 3.88978577 4.41338306]
After being assigned new values, Z is
[0 0 0 0 0 2 2 3 3 4 5]
It's very weird to me that the command Z[I[1]] = M does not assign new values from M to the postion of Z indexed by I[1]. Could you please elaborate on why this problem arises and how to resolve it?
The datatype of your array Z is int, to the values are typecasted by python automatically, resulting in the interger values of int([2.08686055 2.88974949 3.40529229 3.88978577 4.41338306]) = [2 2 3 3 4 5].
If you want to change that behavour, you just need to add a line to change the type of your original array:
Z = Z.astype(float)

Visualize the process of expand and contraction of recursion

I am practicing Exercise 1.17 of SICP
#+begin_src ipython :session alinbx :results output
def fast_mul(a, b):
if b == 1: return a
else:
if even(b): return 2 * fast_mul(a, b//2)
if odd(b): return a + 2 * fast_mul(a, b//2)
def even(n):
return n % 2 == 0
def odd(n):
return n % 2 == 1
print(fast_mul(3, 7))
#+end_src
#+RESULTS:
: 21
How could I see the process of expanding and contraction by adding print as
fast_mul(3,7)
3 + 2 * fast_mul(3, 3)
3 + 2 * (3 + 2 * fast_mul(3, 1))
3 + 2 * (3 + 2 * 3)
21
It sounds like you are looking for a trace, although the defaults may take some hacking to return the specific details you are looking for, eg.
python -m trace -t fast_mul.py
In elisp, default tracing is closer to your desired output, eg.
(defun fast-mul (a b)
(if (eq 1 b) a
(+ (if (evenp b) 0 a) (* 2 (fast-mul a (/ b 2))))))
(trace-function 'fast-mul)
(fast-mul 3 7)
;; 1 -> (fast-mul 3 7)
;; | 2 -> (fast-mul 3 3)
;; | | 3 -> (fast-mul 3 1)
;; | | 3 <- fast-mul: 3
;; | 2 <- fast-mul: 9
;; 1 <- fast-mul: 21
def fast_mul(a, b, s, d):
if b == 1:
print(s,a,') '*d)
return a
else:
if even(b):
print(s+f'2 * fast_mul({a}, {b//2})',') '*d)
return 2 * fast_mul(a, b//2, s+'2 * ( ',d+1)
if odd(b):
print(s+f'{a} + 2 * fast_mul({a}, {b//2})', ') '*d)
return a + 2 * fast_mul(a, b//2,s+f'{a} + 2 * ( ',d+1)
def even(n):
return n % 2 == 0
def odd(n):
return n % 2 == 1
print(fast_mul(3, 7,'',0))
I added two more parameters in the function, s and d.
s stores the string that's carried over from the previous recursion call
d stores the depth of recursion so we can figure out how many closing brackets to add to the string.

Better way to solve simultaneous linear equations programmatically in Python

I have the following code that solves simultaneous linear equations by starting with the first equation and finding y when x=0, then putting that y into the second equation and finding x, then putting that x back into the first equation etc...
Obviously, this has the potential to reach infinity, so if it reaches +-inf then it swaps the order of the equations so the spiral/ladder goes the other way.
This seems to work, tho I'm not such a good mathematician that I can prove it will always work beyond a hunch, and of course some lines never meet (I know how to use matrices and linear algebra to check straight off whether they will never meet, but I'm not so interested in that atm).
Is there a better way to 'spiral' in on the answer? I'm not interested in using math functions or numpy for the whole solution - I want to be able to code the solution. I don't mind using libraries to improve the performance, for instance using some sort of statistical method.
This may be a very naive question from either a coding or maths point of view, but if so I'd like to know why!
My code is as follows:
# A python program to solve 2d simultaneous equations
# by iterating over coefficients in spirals
import numpy as np
def Input(coeff_or_constant, var, lower, upper):
val = int(input("Let the {} {} be a number between {} and {}: ".format(coeff_or_constant, var, lower, upper)))
if val >= lower and val <= upper :
return val
else:
print("Invalid input")
exit(0)
def Equation(equation_array):
a = Input("coefficient", "a", 0, 10)
b = Input("coefficient", "b", 0, 10)
c = Input("constant", "c", 0, 10)
equation_list = [a, b, c]
equation_array.append(equation_list)
return equation_array
def Stringify_Equations(equation_array):
A = str(equation_array[0][0])
B = str(equation_array[0][1])
C = str(equation_array[0][2])
D = str(equation_array[1][0])
E = str(equation_array[1][1])
F = str(equation_array[1][2])
eq1 = str(A + "y = " + B + "x + " + C)
eq2 = str(D + "y = " + E + "x + " + F)
print(eq1)
print(eq2)
def Spiral(equation_array):
a = equation_array[0][0]
b = equation_array[0][1]
c = equation_array[0][2]
d = equation_array[1][0]
e = equation_array[1][1]
f = equation_array[1][2]
# start at y when x = 0
x = 0
infinity_flag = False
count = 0
coords = []
coords.append([0, 0])
coords.append([1, 1])
# solve equation 2 for x when y = START
while not (coords[0][0] == coords[1][0]):
try:
y = ( ( b * x ) + c ) / a
except:
y = 0
print(y)
try:
x = ( ( d * y ) - f ) / e
except:
x = 0
if x >= 100000 or x <= -100000:
count = count + 1
if count >= 100000:
print("It\'s looking like these linear equations don\'t intersect!")
break
print(x)
new_coords = [x, y]
coords.append(new_coords)
coords.pop(0)
if not ((x == float("inf") or x == float("-inf")) and (y == float("inf") or y == float("-inf"))):
pass
else:
infinity_flag if False else True
if infinity_flag == False:
# if the spiral is divergent this switches the equations around so it converges
# the infinity_flag is to check if both spirals returned infinity meaning the lines do not intersect
# I think this would mostly work for linear equations, but for other kinds of equations it might not
x = 0
a = equation_array[1][0]
b = equation_array[1][1]
c = equation_array[1][2]
d = equation_array[0][0]
e = equation_array[0][1]
f = equation_array[0][2]
infinity_flag = False
else:
print("These linear equations do not intersect")
break
y = round(y, 3)
x = round(x, 3)
print(x, y)
equation_array = []
print("Specify coefficients a and b, and a constant c for equation 1")
equations = Equation(equation_array)
print("Specify coefficients a and b, and a constant c for equation 1")
equations = Equation(equation_array)
print(equation_array)
Stringify_Equations(equation_array)
Spiral(equation_array)

What is an order of transitions in state diagram? How to use history pseudo-states?

I read a lot about it, but still not sure in what order states executes (in Composite States) and how exactly deep and shallow history works? Could anybody help me?
I have an example, which I'm not sure how to solve, here it is:
I would appreciate any help!
Question 1:
... not sure .. how exactly deep and shallow history works?
Answer 1:
Note this:
A shallow history is indicated by a small circle containing an "H". It applies to the state region that directly encloses it.
Shallow history pseudostate represents the most recent active substate of its containing state (but not the substates of that substate). ...
Source: http://www.uml-diagrams.org/state-machine-diagrams.html#shallow-history-pseudostate
Question 2:
... I'm not sure if I always should start from initial point, which is outside of all composites?
Answer 2:
Yes. You start from the Initial Pseudostate of the root state (A in this case).
Example:
For the given state-chart and event chain, you would get the following result (simulated with Rhapsody):
after default transition to A
value of x (transition to A): x = 3
value of x (entry A): x = x * 2 = 6
new state: A
after default transition to A::B
new state: A::B
value of x: x = 6
after e1
value of x (entry A::C): x = x + 1 = 7
new state: A::C
after default transition to A::C::G
value of x (entry A::C::G): x = x + 1 = 8
new state: A::C::G
after e3
value of x (exit A::C::G): x = x - 2 = 6
value of x (entry A::C::H): x = x / 2 = 3
new state: A::C::H
after e4
value of x (entry A::C::G): x = x + 1 = 4
new state: A::C::G
after e6
value of x (exit A::C::G): x = x - 2 = 2
value of x (exit A::C): x = x - 1 = 1
value of x (exit A): x = x - 1 = 0
value of x (transition to Y): x = (x * 4) + 2 = 2
new state: Y
after e7
value of x (entry A::C see the note above): x = x + 1 = 3
value of x (entry A::C::G): x = x + 1 = 4
new state: A::C::G
e4 is discarded
after e7
value of x (exit Y): x = x / 2 = 1
value of x (entry A): x = x * 2 = 2
value of x (entry A::C see the note above): x = x + 1 = 3
value of x (entry A::C::G): x = x + 1 = 4
new state: A::C::G

Resources