Why are empty Raku shaped Arrays truthy? - raku

I was a bit surprised to see this:
> say my #i.so
False
> say my #i[3].so
True
Can anyone explain why, in raku, empty Arrays are falsey, yet empty shaped Arrays are truthy?

If the description "empty" refers to "no elements", then there's no such thing as an empty fixed-sized (aka "shaped") array:
say my #unshaped-array; # []
say #unshaped-array.shape; # (*) ("whatever" shape, or "unshaped")
say #unshaped-array.elems; # 0
say #unshaped-array.so; # False
say #unshaped-array[0,1,2]:exists; # (False False False)
say #unshaped-array[0,1,2]:delete; # ((Any) (Any) (Any))
say #unshaped-array[0,1,2]:exists; # (False False False)
say #unshaped-array; # []
say #unshaped-array = [Any,Any,Any]; # [(Any) (Any) (Any)]
say #unshaped-array.elems; # 3
say #unshaped-array.so; # True
say #unshaped-array[0,1,2]:exists; # (True True True)
say #unshaped-array[0,1,2]:delete; # ((Any) (Any) (Any))
say #unshaped-array[0,1,2]:exists; # (False False False)
say #unshaped-array; # []
say my #shaped-array[3]; # [(Any) (Any) (Any)]
say #shaped-array.shape; # (3)
say #shaped-array.elems; # 3
say #shaped-array.so; # True
say #shaped-array[0,1,2]:exists; # (False False False)
say #shaped-array[0,1,2]:delete; # (Nil Nil Nil)
say #shaped-array[0,1,2]:exists; # (False False False)
say #shaped-array; # [(Any) (Any) (Any)]
say #shaped-array = [42]; # [42 (Any) (Any)]
say #shaped-array.elems; # 3
say #shaped-array.so; # True
say #shaped-array[0,1,2]:exists; # (True False False)
say #shaped-array[0,1,2]:delete; # (42 Nil Nil)
say #shaped-array[0,1,2]:exists; # (False False False)
say #shaped-array = [Nil]; # [(Any) (Any) (Any)]
# Just because I named the array "shaped", doesn't mean its shape is fixed:
say #shaped-array := [Nil]; # [(Any)]
say #shaped-array.shape; # (*) ("whatever" shape, or "unshaped")
say #shaped-array := []; # []
say #shaped-array.elems; # 0
say #shaped-array.so; # False
my #i[0]; # Illegal ...
I don't know if there's currently a way to declare a variable that's permanently bound to a fixed shape array.

Related

Leetcode 126: Word Ladder 2 in Python code optimization

I have the solution for the Word Ladder 2 (Leetcode problem 126: Word Ladder 2 ) in Python 3.6, and I notice that one of the very last testcases times out for me on the platform. Funnily, the test passes when run on PyCharm or as an individual test case on the site, but it takes about 5 seconds for it to complete. My solution uses BFS with some optimizations, but can someone tell me if there is a way to make it faster. Thank you! (P.S: Apologies for the additional test cases included in the commented out section!)
import math
import queue
from typing import List
class WordLadder2(object):
#staticmethod
def is_one_hop_away(s1: str, s2: str) -> int:
"""
Uses the distance between strings to return True if string s2 is one character away from s1
:param s1: Base string
:param s2: Comparison string
:return: True if it the difference between the strings is one character
"""
matrix = [[0] * (len(s1) + 1) for i in range(len(s1) + 1)]
for r, row in enumerate(matrix):
for c, entry in enumerate(row):
if not r:
matrix[r][c] = c
elif not c:
matrix[r][c] = r
else:
if s1[r - 1] == s2[c - 1]:
matrix[r][c] = matrix[r - 1][c - 1]
else:
matrix[r][c] = 1 + min(matrix[r - 1][c - 1], matrix[r - 1][c], matrix[r][c - 1])
if matrix[-1][-1] == 1:
return True
else:
return False
def get_next_words(self, s1: str, wordList: List[str]) -> List[str]:
"""
For a given string in the list, return a set of strings that are one hop away
:param s1: String whose neighbors one hop away are needed
:param wordList: Array of words to choose from
:return: List of words that are one character away from given string s1
"""
words = []
for word in wordList:
if self.is_one_hop_away(s1, word):
words.append(word)
return words
def find_ladders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
"""
Main method to determine shortest paths between a beginning word and an ending word, in a given list of words
:param beginWord: Word to begin the ladder
:param endWord: Word to end the ladder
:param wordList: List of words to choose from
:return: List of list of word ladders, if they are found. Empty list, if endWord not in wordList or path not
found from beginWord to endWord
"""
q = queue.Queue()
paths = list()
current = [beginWord]
q.put((beginWord, current))
# Set to track words we have already processed
visited = set()
# Dictionary to keep track of the shortest path lengths to each word from beginWord
shortest_paths = {beginWord: 1}
min_length = math.inf
# Use BFS to find the shortest path in the graph
while q.qsize():
word, path = q.get()
# If endWord is found, add the current path to the list of paths and compute minimum path
# length found so far
if word == endWord:
paths.append(path)
min_length = min(min_length, len(path))
continue
for hop in self.get_next_words(word, wordList):
# If the hop is already processed or in the queue for processing, skip
if hop in visited or hop in q.queue:
continue
# If the shortest path to the hop has not been determined or the current path length is lesser
# than or equal to the known shortest path to the hop, add it to the queue and update the shortest
# path to the hop.
if (hop not in shortest_paths) or (hop in shortest_paths and len(path + [hop]) <= shortest_paths[hop]):
q.put((hop, path + [hop]))
shortest_paths[hop] = len(path + [hop])
visited.add(word)
return [s for s in paths if len(s) == min_length]
if __name__ == "__main__":
# beginword = 'qa'
# endword = 'sq'
# wordlist = ["si","go","se","cm","so","ph","mt","db","mb","sb","kr","ln","tm","le","av","sm","ar","ci","ca","br","ti","ba","to","ra","fa","yo","ow","sn","ya","cr","po","fe","ho","ma","re","or","rn","au","ur","rh","sr","tc","lt","lo","as","fr","nb","yb","if","pb","ge","th","pm","rb","sh","co","ga","li","ha","hz","no","bi","di","hi","qa","pi","os","uh","wm","an","me","mo","na","la","st","er","sc","ne","mn","mi","am","ex","pt","io","be","fm","ta","tb","ni","mr","pa","he","lr","sq","ye"]
# beginword = 'hit'
# endword = 'cog'
# wordlist = ['hot', 'dot', 'dog', 'lot', 'log', 'cog']
# beginword = 'red'
# endword = 'tax'
# wordlist = ['ted', 'tex', 'red', 'tax', 'tad', 'den', 'rex', 'pee']
beginword = 'cet'
endword = 'ism'
wordlist = ["kid","tag","pup","ail","tun","woo","erg","luz","brr","gay","sip","kay","per","val","mes","ohs","now","boa","cet","pal","bar","die","war","hay","eco","pub","lob","rue","fry","lit","rex","jan","cot","bid","ali","pay","col","gum","ger","row","won","dan","rum","fad","tut","sag","yip","sui","ark","has","zip","fez","own","ump","dis","ads","max","jaw","out","btu","ana","gap","cry","led","abe","box","ore","pig","fie","toy","fat","cal","lie","noh","sew","ono","tam","flu","mgm","ply","awe","pry","tit","tie","yet","too","tax","jim","san","pan","map","ski","ova","wed","non","wac","nut","why","bye","lye","oct","old","fin","feb","chi","sap","owl","log","tod","dot","bow","fob","for","joe","ivy","fan","age","fax","hip","jib","mel","hus","sob","ifs","tab","ara","dab","jag","jar","arm","lot","tom","sax","tex","yum","pei","wen","wry","ire","irk","far","mew","wit","doe","gas","rte","ian","pot","ask","wag","hag","amy","nag","ron","soy","gin","don","tug","fay","vic","boo","nam","ave","buy","sop","but","orb","fen","paw","his","sub","bob","yea","oft","inn","rod","yam","pew","web","hod","hun","gyp","wei","wis","rob","gad","pie","mon","dog","bib","rub","ere","dig","era","cat","fox","bee","mod","day","apr","vie","nev","jam","pam","new","aye","ani","and","ibm","yap","can","pyx","tar","kin","fog","hum","pip","cup","dye","lyx","jog","nun","par","wan","fey","bus","oak","bad","ats","set","qom","vat","eat","pus","rev","axe","ion","six","ila","lao","mom","mas","pro","few","opt","poe","art","ash","oar","cap","lop","may","shy","rid","bat","sum","rim","fee","bmw","sky","maj","hue","thy","ava","rap","den","fla","auk","cox","ibo","hey","saw","vim","sec","ltd","you","its","tat","dew","eva","tog","ram","let","see","zit","maw","nix","ate","gig","rep","owe","ind","hog","eve","sam","zoo","any","dow","cod","bed","vet","ham","sis","hex","via","fir","nod","mao","aug","mum","hoe","bah","hal","keg","hew","zed","tow","gog","ass","dem","who","bet","gos","son","ear","spy","kit","boy","due","sen","oaf","mix","hep","fur","ada","bin","nil","mia","ewe","hit","fix","sad","rib","eye","hop","haw","wax","mid","tad","ken","wad","rye","pap","bog","gut","ito","woe","our","ado","sin","mad","ray","hon","roy","dip","hen","iva","lug","asp","hui","yak","bay","poi","yep","bun","try","lad","elm","nat","wyo","gym","dug","toe","dee","wig","sly","rip","geo","cog","pas","zen","odd","nan","lay","pod","fit","hem","joy","bum","rio","yon","dec","leg","put","sue","dim","pet","yaw","nub","bit","bur","sid","sun","oil","red","doc","moe","caw","eel","dix","cub","end","gem","off","yew","hug","pop","tub","sgt","lid","pun","ton","sol","din","yup","jab","pea","bug","gag","mil","jig","hub","low","did","tin","get","gte","sox","lei","mig","fig","lon","use","ban","flo","nov","jut","bag","mir","sty","lap","two","ins","con","ant","net","tux","ode","stu","mug","cad","nap","gun","fop","tot","sow","sal","sic","ted","wot","del","imp","cob","way","ann","tan","mci","job","wet","ism","err","him","all","pad","hah","hie","aim"]
wl = WordLadder2()
# beginword = 'hot'
# endword = 'dog'
# wordlist = ['hot', 'dog', 'dot']
print(wl.find_ladders(beginword, endword, wordlist))
The part that slows down your solution is is_one_hop_away, which is a costly function. This is called repeatedly during the actual BFS. Instead you should aim to first create a graph structure -- an adjacency list -- so that complexity of calculating which words are neighbors is dealt with before actually peforming the BFS search.
Here is one way to do it:
from collections import defaultdict
class Solution:
def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
def createAdjacencyList(wordList):
adj = defaultdict(set)
d = defaultdict(set)
for word in wordList:
for i in range(len(word)):
derived = word[:i] + "*" + word[i+1:]
for neighbor in d[derived]:
adj[word].add(neighbor)
adj[neighbor].add(word)
d[derived].add(word)
return adj
def edgesOnShortestPaths(adj, beginWord, endWord):
frontier = [beginWord]
edges = defaultdict(list)
edges[beginWord] = []
while endWord not in frontier:
nextfrontier = set(neighbor
for word in frontier
for neighbor in adj[word]
if neighbor not in edges
)
if not nextfrontier: # endNode is not reachable
return
for word in frontier:
for neighbor in adj[word]:
if neighbor in nextfrontier:
edges[neighbor].append(word)
frontier = nextfrontier
return edges
def generatePaths(edges, word):
if not edges[word]:
yield [word]
else:
for neighbor in edges[word]:
for path in generatePaths(edges, neighbor):
yield path + [word]
if endWord not in wordList: # shortcut exit
return []
adj = createAdjacencyList([beginWord] + wordList)
edges = edgesOnShortestPaths(adj, beginWord, endWord)
if not edges: # endNode is not reachable
return []
return list(generatePaths(edges, endWord))

issue with update shown values in a pyqt5-applet (using qtableview)

I want to make a qtableview widget correctly updating. I'm working on a calibration applet, where i wanna fill cell by cell of an (e. g.) 100 x 100 x 4 array.
If my hardware reaches position 1, 2, 3, and so on, I will trigger a voltage measurement and gather those values with an i2c-read out-function.
So issues a la "my qtableview is not updating" are omnipresent.
But so far, I'm not able to adapt examples I have read, to make my code behaving as I want.
So if you look at my screenshot:
the problem is:
when I'm clicking on row or col +/-, the yellow highlighting is not changing instantly
when I'm clicking on store i²c, which is meant to put a dummy 0.0 in/on selected cell, this is also not changing instantly
Several methods like telling the model that data has changed, I was not able to implement correctly so far.
Could some of you help me to add a few lines just to force applet to update correctly?
fillCSV_forum.py:
### libraries:
import sys # to use e. g. exit function
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import pandas as pd # to use pandas tables
import numpy as np # to use numpy arrays
### user-defined header files / modules:
from uLib_coloredWidget import Color # import user-defined functions..
from rndGen import i2c_read # .. see folder
### initial settings:
# general
np.random.seed(4) # if using np.random, then pseudo random values will occure
### globals:
nRow = 5; nCol = 5; nSht = 4 # table dimensions
rowIdx = colIdx = shtIdx = 0 # aux vars to index array
rndArray = np.random.rand(nSht, nRow, nCol) * 4.3 # auxilliary before integrating i2c
tabNames = ["A4", "A5","A6","A7"] # array (list) with tab names
rowIdx = 1; colIdx = 1 # aux vars to index selected cell
### declarations / definitions:
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role == Qt.BackgroundRole and index.column() == colIdx and index.row() == rowIdx:
# See below for the data structure.
return QtGui.QColor('yellow')
if role == Qt.DisplayRole:
value = self._data.iloc[index.row(), index.column()]
if isinstance(value, float): # to set fixed DISPLAYED precision of floats
return "%.4f" % value
return str(value)
def rowCount(self, index):
return self._data.shape[0]
def columnCount(self, index):
return self._data.shape[1]
def headerData(self, section, orientation, role):
# section is the index of the column/row.
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._data.columns[section])
if orientation == Qt.Vertical:
return str(self._data.index[section])
class App(QtWidgets.QMainWindow):
# local variable's declarations
# init
def __init__(self):
super().__init__() # default one
self.setup_main_window() # using helper function to increase readability (function call within self scope)
# setup main window
self.createLayout() # function call to create layouts with widgets
self.post_main_window() # pass edited layouts to main window
# declaration / methods / helper functions
def setup_main_window(self): # to set window's / applet's properties
self.centralwidget = QtWidgets.QWidget()
self.setCentralWidget(self.centralwidget)
self.resize( 800, 400 )
self.setWindowTitle( "# disposition calibration #" )
def post_main_window(self): # to publish edited layouts in app window
self.centralwidget.setLayout(self.lyoOut)
def createLayout(self): # to create layouts with widgets
self.lyoOut = QtWidgets.QVBoxLayout() # declare different layouts
self.lyoIn1 = QtWidgets.QHBoxLayout()
self.lyoIn2 = QtWidgets.QGridLayout()
self.createWidgets() # function call pass widgets to sub-layouts
self.lyoOut.addLayout(self.lyoIn1) # inner layouts got widgets by self.createWidgets()
self.lyoOut.addLayout(self.lyoIn2) # merge edited inner layout in/to outside layout here
def createWidgets(self): # create master-layout's widgets (function calls)
# fill 1st row of ouside layout
self.lyoIn1 = self.createNestedTabs(self.lyoIn1) # function call to create master-tabs
# fill 2nd row of outside layout
self.lyoIn2 = self.createButtons(self.lyoIn2) # function call to create buttons
def createNestedTabs(self, layout2modify): # create 1st tab layer
self.MstTabs = QtWidgets.QTabWidget() # create tabs-widget
self.MstTabs.setTabPosition(QtWidgets.QTabWidget.North) # set it's location
self.MstTabs.addTab(self.createChildTabs(), "data") # add several sub-tab layouts to that widget
self.MstTabs.addTab(Color("orange"), "plot") #
stylesheet = """
QTabBar::tab:selected {background: lightgreen;}
QTabBar::tab:!selected {background: lightyellow;}
"""
self.MstTabs.setStyleSheet(stylesheet)
layout2modify.addWidget(self.MstTabs) # add this tabs-widget to passed-in layout
return layout2modify # return edited layout
def createChildTabs(self): # create 2nd tab layer
self.ChdTabs = QtWidgets.QTabWidget() # create tabs-widget
self.ChdTabs.setTabPosition(QtWidgets.QTabWidget.West) # set it's location
self.ChdTabs.addTab(self.createPandasTables(0), "A4")
self.ChdTabs.addTab(self.createPandasTables(1), "A5")
self.ChdTabs.addTab(self.createPandasTables(2), "A6")
self.ChdTabs.addTab(self.createPandasTables(3), "A7")
return self.ChdTabs # return created widgets
def createPandasTables(self, shtIdx): # to creating and editing pandas tables-widgets
# use indexed (pandas)dataframe sheet values
Lbl = ["a","b","c","d","e"]
self.df = pd.DataFrame(rndArray[shtIdx], columns = Lbl, index = Lbl)
# .. to create a widget
self.table_widget = QtWidgets.QTableView() # create QTableView-Widget
self.model = TableModel(self.df) # make df to user defined table model to use in widgets
self.table_widget.setModel(self.model) # pass created model to created widget
# certain formatings
self.table_widget.resizeColumnsToContents() # set column width to content
self.table_widget.horizontalHeader().setStretchLastSection(True) # strech last column to frame width
self.table_widget.verticalHeader().setStretchLastSection(True) # strech last row to frame height
self.table_widget.setAlternatingRowColors(True) # switch on alternating row highlighting
return self.table_widget # return created widgets
def createButtons(self, layout2modify): # helper function - to create layout's buttons
bStoreI2C = QtWidgets.QPushButton("Store i²c")
bStoreI2C.clicked.connect(lambda:self.storeVal())
bStoreI2C.setStyleSheet("QPushButton::hover"
"{"
"background-color : yellow;"
"}")
layout2modify.addWidget(bStoreI2C, 1, 3, 2, 1)
self.lbl_1 = QtWidgets.QLabel()
self.lbl_1.setText(str(rowIdx))
self.lbl_1.setAlignment(QtCore.Qt.AlignCenter)
layout2modify.addWidget(self.lbl_1, 1, 5, 2, 1)
bRowAdd = QtWidgets.QPushButton("row +")
bRowAdd.clicked.connect(lambda:self.rowAdd())
layout2modify.addWidget(bRowAdd, 2, 6)
bRowSub = QtWidgets.QPushButton("row -")
bRowSub.clicked.connect(lambda:self.rowSub())
layout2modify.addWidget(bRowSub, 1, 6)
return layout2modify # return edited layout
def storeVal(self):
#i2c_vals = get_i2c_values(i2c_addrs)
for i in range (0,4):
#self.tbData[i, rowIdx, colIdx] = i2c_vals[i] # change cell entries with imported value
rndArray[i, rowIdx, colIdx] = 0
#self.tbData[sht, row, col] = 99 # change cell entry with imported value
# try 1
#self.table_widget.update()
#self.table_widget.repaint()
#self.model.select()
#self.table_widget.select()
# try 2
# self.refreshModel() # not working so far
#self.model = TableModel(self.df) # make df to user defined table model to use in widgets
#self.table_widget.setModel(self.model)
# print(rndArray)
print('i²c-value(s) stored')
def rowAdd(self):
global rowIdx
rowIdx = (rowIdx + 1) % nRow # increment and modulo to cycle
self.lbl_1.setText(str(rowIdx)) # update label's text
print('row is ', rowIdx)
def rowSub(self):
global rowIdx
rowIdx = (rowIdx - 1) % nRow # increment and modulo to cycle
self.lbl_1.setText(str(rowIdx)) # update label's text
print('row is ', rowIdx)
### main:
def main():
app = QtWidgets.QApplication(sys.argv) # instanciate app
window = App() # instanciate window
window.show() # show window
app.exec_() # stuck here 'til window is closed
print('# window will be terminated.. #')
time.sleep(2)
print('# ..app execution closed #')
# make file executable
if __name__ == '__main__':
main()
rndGen.py: (is called in fillCSV_forum.py)
import numpy as np
def i2c_read():
floats = np.random.rand(4,1,1) * 4.3
return floats
uLib_coloredWidget.py: (is called in fillCSV_forum.py)
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtWidgets import QWidget
class Color(QWidget):
def __init__(self, color):
super().__init__()
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
pip freeze --local-output of virtual enviroment:
numpy==1.23.0
pandas==1.4.3
PyQt5==5.15.7
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.0
python-dateutil==2.8.2
pytz==2022.1
six==1.16.0
[... additionally many hours of trial and error....]
i think i finally got a dirty solution / work around..
the problem i could determining, was e. g. if i am clicking the col+/- or store button, the focus of recently selected tab is vanishing.
first when click again into any tab region or select another tabs those values are updating.
so i tried to look for programmatically tab swap and did this as a dirty work around because i could not find a method like "reactivate tab again"
i added ... :
def storeVal(self):
#i2c_vals = get_i2c_values(i2c_addrs)
for i in range (0,nSht):
self.df[i].iat[rowIdx, colIdx] = 99
print('i²c-value(s) stored')
self.show_data()
def show_data(self):
x = self.ChdTabs.currentIndex()
print(x) # debugging
self.ChdTabs.setCurrentIndex(1)
self.ChdTabs.setCurrentIndex(x)
... a show method and called it at the end of the store-method.
in this show method i programmatically swap the active tab back and forth. this is so fast, that i cannot see it
now my values are correctly shown
another tiny if else code is necessary to also swap if tab 1 is selected, but this is cosmetic thing

Numba "LLVM IR parsing error" seemingly because numba.complex128[:,:].shape has a default type?

Please bear with the long question.
Numba encounters "LLVM IR parsing error" in my code seemingly due to defualt typing of np.complex128.shape, but I could not find any documentations saying that np.complex128.shape, numba.complex128.shape or prange have default types.
Minimal workable reproduction:
import numpy as np
from numba import jit, njit, prange
from numba import complex128, int32 # import jit value types
# Invert an (n,n) submatrix of a (m>n,n) rectangular matrix by taking the first
# n rows. "Taking the first n rows" is motivated by the RHS being rank n.
#
# -- Input --
# (m,n) matrix A
#
# -- Return --
# (m,m) matrix A_inv
#njit(complex128[:,:](complex128[:,:]))
def inv_square_jit(in_matrix):
if in_matrix.ndim != 2:
raise ValueError("Input should be 2d array")
n_row = in_matrix.shape[0]
n_col = in_matrix.shape[1]
if n_row<=n_col:
raise ValueError("Input should have more rows than cols")
# Remove specfied column (slightly faster than delete)
# and remove extra rows
sqinv = np.linalg.inv(in_matrix[:n_col, :])
padded = np.zeros((n_row, n_row), dtype = np.complex128)
padded[:len(sqinv), :len(sqinv)] = sqinv
return(padded)
# Solve degenerate underdetermined equation system
# -- Input --
# (m,n+1), (m,n), rank-n 2d np arrays A, B
# n-dim np array-like vb
# or
# (m,n+1), rank n+1 A,
# m-dim np array-like v_rhs
#
# vb can be any array-like item, and is not necessarily 1d.
# Implemented with ChiPhiFunc in mind.
#
# -- Return --
# n+1 np array-like va
#
# -- Note --
# For recursion relations with ChiPhiFunc's, A and B should come from
# convolution matrices. That still needs implementation.
#njit(complex128[:](complex128[:,:], complex128[:]))
def solve_degenerate_jit(A, v_rhs):
n_dim = A.shape[1]
if A.shape[0] != v_rhs.shape[0]:
raise ValueError("solve_underdetermined: A, v_rhs must have the same number of rows")
A_inv = np.ascontiguousarray(inv_square_jit(A))
# This vector is actually m-dim, with m-n blank elems at the end.
va = (A_inv#np.ascontiguousarray(v_rhs))[:n_dim]
return(va)
# #njit(complex128[:](complex128[:,:], complex128[:,:], complex128[:]))
# def solve_degenerate_jit(A, B, vb):
# B_cont = np.ascontiguousarray(B)
# vb_cont = np.ascontiguousarray(vb)
# return(solve_degenerate_jit(A, B_cont#vb_cont))
# Generate convolution operator from a for an n_dim vector.
#njit(complex128[:,:](complex128[:], int32))
def conv_matrix(vec, n_dim):
out_transposed = np.zeros((n_dim,len(vec)+n_dim-1), dtype = np.complex128)
for i in prange(n_dim):
out_transposed[i, i:i+len(vec)] = vec
return(out_transposed.T)
# For solving a*va = v_rhs, where va, vb have the same number of dimensions.
# In the context below, "#dim" represents number of chi mode components.
#
# -- Input --
# v_source_A: 2d matrix, content of ChiPhiFuncGrid, #dim = a
# v_rhs: 2d matrix, content of ChiPhiFuncGrid, #dim = m
# rank_rhs: int, rank of v_rhs (and correct answer)
# -- Output --
# va: 2d matrix, content of ChiPhiFuncGrid. Has #dim = rank_rhs
#njit(complex128[:,:](complex128[:,:], complex128[:,:], int32), parallel=True)
def batch_degen_jit(v_source_A, v_rhs, rank_rhs):
# if type(v_source_A) is not ChiPhiFuncGrid or type(v_source_B) is not ChiPhiFuncGrid:
# raise TypeError('batch_underdetermined_deconv: input should be ChiPhiFuncGrid.')
A_slices = np.ascontiguousarray(v_source_A.T) # now the axis 0 is phi grid
v_rhs_slices = np.ascontiguousarray(v_rhs.T) # now the axis 0 is phi grid
# axis 0 is phi grid, axis 1 is chi mode
va_transposed = np.zeros((len(A_slices), rank_rhs), dtype = np.complex128)
if len(A_slices) != len(v_rhs_slices):
raise ValueError('batch_underdetermined_deconv: A, v_rhs must have the same number of phi grids.')
if len(v_source_A) + rank_rhs - 1 != len(v_rhs):
raise ValueError('batch_underdetermined_deconv: #dim_A + rank_rhs - 1 = #dim_v_rhs must hold.')
for i in prange(len(A_slices)):
A_conv_matrix_i = conv_matrix(A_slices[i], rank_rhs)
# ********** Removing this line somehow makes it compile **********
va_transposed[i, :] = solve_degenerate_jit(A_conv_matrix_i,v_rhs_slices[i])
# ********** Removing this line somehow makes it compile **********
return va_transposed.T
The code compiles fine with parallel=False for the last method. However, with parallel=True, error occurs in for i in prange(len(A_slices)): of def batch_degen_jit(v_source_A, v_rhs, rank_rhs):, seemingly because solve_degenerate_jit(complex128[:,:], complex128[:], int32) accepts int32, but the prange(len(A_slices)) produces int64. Replacing all int32 with int64 solves the problem. Removing the *-marked line also makes it compile.
Error:
LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
Failed in nopython mode pipeline (step: nopython mode backend)
LLVM IR parsing error
<string>:1278:34: error: '%.777' defined with type 'i64' but expected 'i32'
%".778" = icmp eq i32 %".776", %".777"
^
File "<ipython-input-24-fa65c2d527fa>", line 104:
def batch_degen_jit(v_source_A, v_rhs, rank_rhs):
<source elided>
raise ValueError('batch_underdetermined_deconv: #dim_A + rank_rhs - 1 = #dim_v_rhs must hold.')
for i in prange(len(A_slices)):
^
During: lowering "id=17[LoopNest(index_variable = parfor_index.1805, range = (0, $10call_method.4_size0.1767, 1))]{120: <ir.Block at <ipython-input-24-fa65c2d527fa> (104)>}Var(parfor_index.1805, <ipython-input-24-fa65c2d527fa>:104)" at <ipython-input-24-fa65c2d527fa> (104)
Why is this the case?
Thank you!
(P.S. here's a test case for the methods:
convolver = np.random.rand(10,3)
correct_answer = np.random.rand(10,5)
rhs = np.zeros((10,7))
for i in range(10):
rhs[i] = np.convolve(convolver[i], correct_answer[i])
print(batch_degen_jit(np.complex128(convolver).T, np.complex128(rhs).T, 5))
)

Disable or Bypass login of odoo when trying to hit from external application

I am trying to open odoo url from my hosted application but its redirecting to login screen. As user is already logged in to my application logically user should not be redirected to login screen again...How can I bypass this security check of odoo???
Thanks In advance
From your question, I think what you are trying to achieve is to authenticate your user's odoo session automatically if that user is already authenticated in your non-odoo application. To achieve that, you can implement your application such that, on authentication of a user, your backend will authenticate a session in odoo with corresponding user, and set session_id cookie of user's browser to that authenticated session_id. I guess that may be achievable if both application are served under same domain with reverse proxying using nginx or apache, as other's already commented, there is no way you can totally disable or bypass authentication of odoo itself, as this is a well developed business related software, and that will just defeat it's purpose.
It is possible to bypass the security of odoo. These changes are required in these two files
`
**server/odoo/http.py**
line number 406 in odoo 12
def validate_csrf(self, csrf):
# if not csrf:
# return False
#
# try:
# hm, _, max_ts = str(csrf).rpartition('o')
# except UnicodeEncodeError:
# return False
#
# if max_ts:
# try:
# if int(max_ts) < int(time.time()):
# return False
# except ValueError:
# return False
#
# token = self.session.sid
#
# msg = '%s%s' % (token, max_ts)
# secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
# assert secret, "CSRF protection requires a configured database secret"
# hm_expected = hmac.new(secret.encode('ascii'), msg.encode('utf-8'), hashlib.sha1).hexdigest()
# return consteq(hm, hm_expected)
return True
def setup_session(self, httprequest):
explicit_session = True
# recover or create session
# session_gc(self.session_store)
#
# sid = httprequest.args.get('session_id')
# explicit_session = True
# if not sid:
# sid = httprequest.headers.get("X-Openerp-Session-Id")
# if not sid:
# sid = httprequest.cookies.get('session_id')
# explicit_session = False
# if sid is None:
# httprequest.session = self.session_store.new()
# else:
# httprequest.session = self.session_store.get(sid)
httprequest.session = self.session_store.new()
httprequest.session.uid =2
httprequest.session.login = 'root'
httprequest.session.db = 'odoo'
httprequest.session.sid = '7aa5500f30365aead781465ec08bbb03c3a5024b'
return explicit_session
line number 1348
def setup_session(self, httprequest):
explicit_session = True
# recover or create session
# session_gc(self.session_store)
#
# sid = httprequest.args.get('session_id')
# explicit_session = True
# if not sid:
# sid = httprequest.headers.get("X-Openerp-Session-Id")
# if not sid:
# sid = httprequest.cookies.get('session_id')
# explicit_session = False
# if sid is None:
# httprequest.session = self.session_store.new()
# else:
# httprequest.session = self.session_store.get(sid)
httprequest.session = self.session_store.new()
httprequest.session.uid =2
httprequest.session.login = 'root'
httprequest.session.db = 'odoo'
httprequest.session.sid = '7aa5500f30365aead781465ec08bbb03c3a5024b'
return explicit_session
**server/odoo/service/security.py**
line number 18
def check_session(session, env):
# self = env['res.users'].browse(session.uid)
# expected = self._compute_session_token(session.sid)
# if expected and odoo.tools.misc.consteq(expected, session.session_token):
# return True
# self._invalidate_session_cache()
return True

Finding a cycle in a DFS directed graph

I'm trying to find a cycle in an directed graph using a dfs search. I'm reading in the file from a text file that holds all the neighbors of a vertex. Whenever I call the cycle_exists method I keep getting all false, so the answer never changes.
Vertex.py
"""
__version__ = 'October 2015'
Vertex class reads in our graph and
performs a depth first search on it
and performs the transitive closure operation.
Vertex class also checks for cycles in our graph.
"""
import sys
class Graph:
def __init__(self):
"""
Initialize the variable used in Graph
"""
self.dfsPaths = [] #list for dfsPaths
self.VertexList = {} #list for adjacent vertices
def readInputGraph(self, inputFile):
"""
Reads specified input file and stores in
adjacency list
:param inputFile: file to be rad in
:return: the VertexList
"""
file = open(inputFile, 'r') #open the file and read it
for line in file: #for each element in the file
(vertex,val) = line.split() #vertex gets first value in the line, val gets second
if vertex not in self.VertexList: #if vertex not in VertexList
self.VertexList[vertex] = set([val]) #add adjacent pairs
else: #else
self.VertexList.get(vertex).add(val) #add the values
for i in list(self.VertexList.keys()): #for each element in the list of the vertex keys
for j in self.VertexList[i]: # for each vertex that's in i
if j not in self.VertexList: #if j is not in the vertex list
self.VertexList[j] = set() #we add it to the vertex list
return self.VertexList #return list of adjacent vertices
def dfsSearch(self, graph, start, end, path = []):
"""
Performs a depth first search on
the graph that is read in from the file
:param graph: the graph that we are performing the search on
:param start: the starting vertex
:param end: the target vertex
:param path: a list of the paths
:return: the paths from the search
"""
path = path + [start] #path
if start == end: #if the start element and end element are the same
return [path] #return the list of paths
if start not in graph: #if the start element is not in the graph
print( 'Not Found')#prints out not found
return [] #return an empty list
paths = [] #path list
for node in graph[start]: #for node in the graph
if node not in path: #if not in the path
newpaths = self.dfsSearch(graph, node, end, path) #new paths we found
for newpath in newpaths: #for each new path in the list of new paths
paths.append(newpath) #add the new path to our list of paths
paths.sort() #sort our paths
self.cycle_exists(graph)
#print(self.cycle_exists(graph))
return paths #return our paths
def cycle_exists(self, graph): # -graph is our graph.
color = { node : "white" for node in graph} #color all nodes white to begin with
found_cycle = False # found_cycle set to false
for node in graph: # for each node in graph.
if color[node]:#if the color[node] is white
self.dfs_visit(graph, node, color, found_cycle) #we call the dfs_visit method
if found_cycle:#if a cycle is found
found_cycle = True
break#break
return found_cycle #return the true or false
def dfs_visit(self,graph, node, color, found_cycle):
#print(color)
if found_cycle: # if a cycle is found return to the cycle_exists method
return
color[node] = "gray"#else color the node gray
for neighbor in graph[node]: #for every neighbor in the graph of the node
if color[neighbor] == "gray": #If neighbor is gray
found_cycle = True # then a cycle exists.
return
if color[neighbor] == "white": #if the neighbor is white
#print(color[neighbor])
self.dfs_visit(graph, neighbor, color, found_cycle)# call dfs_visit .
color[node] = "black"# color the original node black
GraphDriver.py
from Vertex import *
import sys
class GraphDriver:
def __init__(self):
self.graph = Graph()
def main():
graph = Graph()
inFile = sys.argv[1]
d = graph.readInputGraph(inFile)
userInput = input("Enter a source and destination:")
dog = userInput.split(" ", -1)
for path in graph.dfsSearch(d, dog[0], dog[1]):
print(path)
if __name__ == '__main__':
main()
Input.txt
0 1
0 6
1 2
1 5
2 3
2 4
4 3
4 0
5 4
6 5
The problem with your code is that it expects the boolean variable found_cycle to be passed by-reference to dfs_visit. However, Python does pass by-value (link, link). Therefore, when dfs_visit sets the parameter found_cycle to True, this modification will not affect the found_cycle variable passed into dfs_visit by the caller.
You can fix this by changing dfs_visit to return whether a cycle was found:
def cycle_exists(self, graph):
color = { node : "white" for node in graph}
for node in graph:
if color[node] == "white":
if self.dfs_visit(graph, node, color):
return True
return False
def dfs_visit(self,graph, node, color):
color[node] = "gray"
for neighbor in graph[node]:
if color[neighbor] == "gray":
return True
if color[neighbor] == "white":
if self.dfs_visit(graph, neighbor, color):
return True
color[node] = "black"
return False
Background information
Regarding the passing of boolean variables, consider the following example:
def f(my_bool):
my_bool = True
my_bool = False
f(my_bool)
print(my_bool)
This code will print False. In the global scope, the variable my_bool is initialized with False and is then passed to f. It is passed by-value, so in f the parameter my_bool receives the value False. However, this variable my_bool is unrelated to the variable my_bool outside f. So modifying the my_bool in f does not affect the my_bool outside f.
Note that this does not mean that you cannot pass references to objects, only that the reference is passed by-value. Consider the following example:
class MyObject:
def __init__(self):
self.x = 13
def f(my_object):
my_object.x = 17
def g(my_object):
my_object = MyObject()
my_object.x = 19
my_object = MyObject()
print(my_object.x)
f(my_object)
print(my_object.x)
g(my_object)
print(my_object.x)
This example prints:
13
17
17
In the global scope, the variable my_object is initialized with an instance of MyObject. The constructor of MyObject initializes the member variable x to 13, which is the first printed value. The my_object variable is then passed to the function f. The variable is passed by-value, so the variable my_object in f is a different variable than the variable my_object in the global scope. However, both point to the same instance of MyObject. So when f sets my_object.x = 17, the next print in the global scope will show this value.
Next, in the global scope the variable my_object is passed to g. Again, the variable is passed by-value, so the variable my_object in g is different from the variable my_object in the global scope, but both point to the same instance of MyObject. In g the my_object variable is then assigned a new instance of MyObject. This does not affect the my_object in the global scope, which still points to the previous instance of MyObject. Therefore, the final print in the global scope will still show the 17 that has been assigned to the x of the first instance of MyObject, not the 19 that was assigned in g to the x in the second instance of MyObject.
So this is why e.g. your color variable is not affected by the same problem as your found_cycle variable. For color, you pass by-value for each call to dfs_visit, as for found_cycle, but you never assign a new value to color in dfs_visit. Therefore, the modifications done to color are done to the same object as pointed to by the original color variable in the cycle_exists function.