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.