it is possible set time limit to read input in terminal in Lua.
For example you habe only 1 second to write a letter else program skip this action.
thanks for any tip ;)
You can do this by changing the terminal settings (see man termios) using luaposix (on POSIX machines only, obviously):
local p = require( "posix" )
local function table_copy( t )
local copy = {}
for k,v in pairs( t ) do
if type( v ) == "table" then
copy[ k ] = table_copy( v )
else
copy[ k ] = v
end
end
return copy
end
assert( p.isatty( p.STDIN_FILENO ), "stdin not a terminal" )
-- derive modified terminal settings from current settings
local saved_tcattr = assert( p.tcgetattr( p.STDIN_FILENO ) )
local raw_tcattr = table_copy( saved_tcattr )
raw_tcattr.lflag = bit32.band( raw_tcattr.lflag, bit32.bnot( p.ICANON ) )
raw_tcattr.cc[ p.VMIN ] = 0
raw_tcattr.cc[ p.VTIME ] = 10 -- in tenth of a second
-- restore terminal settings in case of unexpected error
local guard = setmetatable( {}, { __gc = function()
p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, saved_tcattr )
end } )
local function read1sec()
assert( p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, raw_tcattr ) )
local c = io.read( 1 )
assert( p.tcsetattr( p.STDIN_FILENO, p.TCSANOW, saved_tcattr ) )
return c
end
local c = read1sec()
print( "key pressed:", c )
The lcurses (ncurses for Lua) Lua library might provide this. You would have to download and install it. There is an example of how to check for keypress only at Create a function to check for key press in unix using ncurses, it is in C but the ncurses API is identical in Lua.
Otherwise, you will have to create a Lua extension module using the C/C++ API: you would create C function that you call from Lua, and this C function then has access to the OS's usual function like getch, select, etc (depends if you are on Windows or Linux).
Related
local function Numeral(roman)
local symbols = {}
local sum = 0
for i = 1,#roman do
local val = roman:sub(i,i)
sum = sum + symbols[val]
end
return sum
end
print(Numeral('II'))
Basically, I'm making a roman numeral to number converter. What I want to do is access a key in a dictionary with a variable like
local var = 'I'
local something = dictionary.var
But with what I'm doing, it may be a bit more complicated. Is it possible?
When using a table for the roman numbers then a metatable with the table functions in __index make things a bit easier.
This example show what i mean...
> _VERSION
Lua 5.4
> romans=setmetatable({},{__index=table})
> romans:insert('I')
> romans:insert('II')
> romans:insert('III')
> romans:insert('IV')
> romans:insert('V')
> romans:insert('VI')
> romans:insert('VII')
> romans:insert('VIII')
> romans:insert('VIIII')
> romans:insert('X')
> romans:concat(', ',1,10)
I, II, III, IV, V, VI, VII, VIII, VIIII, X
( Done in a interactive Lua console ( lua -i ) )
For more about doing converting from and to roman numbers you can read also...
https://gist.github.com/efrederickson/4080372
But be aware its not free of bugs.
You can do it better ;-)
The problem I am faced with regards to llvmlite is producing a simple hello world example.
I am unable to display the string global variable value in the function I created.
It appears to always print out the number one.
I have already tried to return the stringtype which produced a error.
from llvmlite import ir
i64 = ir.IntType(64)
i8 = ir.IntType(16)
hellostr = 'hello, world!'
stringtype = ir.ArrayType(i64, len(hellostr))
module = ir.Module( name="m_hello_example" )
hello = ir.GlobalVariable(module, stringtype, '.str4')
fn_int_to_int_type = ir.FunctionType(i64, [stringtype.as_pointer()] )
fn_hel = ir.Function( module, fn_int_to_int_type, name="fn_hel" )
fn_hel_block = fn_hel.append_basic_block( name="fn_hel_entry" )
builder = ir.IRBuilder(fn_hel_block )
# zero = builder.constant(i64, 0)
# const_1 = ir.Constant(stringtype,1);
# builder.ret(const_1)
const_1 = ir.Constant(i64,1);
# print(const_1)
builder.ret(const_1)
print( module )
I was expecting the output to print out the string 'hello, world!'.
Any help would be much appreciated.
Thanks.
It ended up that I was able to solve my problem with the following code:
import llvmlite.ir as ir
import llvmlite.binding as llvm
from ctypes import CFUNCTYPE
def main():
m = ir.Module()
func_ty = ir.FunctionType(ir.VoidType(), []) #defining printer function as type void
func = ir.Function(m, func_ty, name="printer") #define function as printer
builder = ir.IRBuilder(func.append_basic_block('entry')) #defining the entry point of the function printer
fmt = "%s\n\0" #in function printf allows for inserting arg in, next global_fmt statements allow for creating #"fstr" assignment
c_fmt = ir.Constant(ir.ArrayType(ir.IntType(8), len(fmt)),
bytearray(fmt.encode("utf8")))
global_fmt = ir.GlobalVariable(m, c_fmt.type, name="fstr")
global_fmt.linkage = 'internal'
global_fmt.global_constant = True
global_fmt.initializer = c_fmt
arg = "Hello, World!\0" #args will be passed into printf function.
c_str_val = ir.Constant(ir.ArrayType(ir.IntType(8), len(arg)),
bytearray(arg.encode("utf8"))) #creates the c_str_value as a constant
printf_ty = ir.FunctionType(ir.IntType(32), [], var_arg=True) #creation of the printf function begins here and specifies the passing of a argument
printf = ir.Function(m, printf_ty, name="printf")
c_str = builder.alloca(c_str_val.type) #creation of the allocation of the %".2" variable
builder.store(c_str_val, c_str) #store as defined on the next line below %".2"
voidptr_ty = ir.IntType(8).as_pointer()
fmt_arg = builder.bitcast(global_fmt, voidptr_ty) #creates the %".4" variable with the point pointing to the fstr
builder.call(printf, [fmt_arg, c_str]) #We are calling the prinf function with the fmt and arg and returning the value as defiend on the next line
builder.ret_void()
#Next lines are for calling llvm and returning the assembly.
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
print(str(m)) #PRINTING OUT THE ASSEMBLY
llvm_module = llvm.parse_assembly(str(m)) #Parsing teh assembly
tm = llvm.Target.from_default_triple().create_target_machine() #creating the target machine
with llvm.create_mcjit_compiler(llvm_module, tm) as ee:
ee.finalize_object() #Making sure all modules owned by the execution engine are fully processed and usable for execution
fptr = ee.get_function_address("printer") #fptr will reference the printer function
py_func = CFUNCTYPE(None)(fptr)
py_func() #run the function printer
if __name__ == "__main__":
main()
It appears that I didn't correctly assign the variable and hence why I wasn't returning anything.
I try to calculate recusively the GCD of several numbers.
Here my try. with more than numbers two is an erverlasting loop.
I'm not sure about the pgcd( unpack(arg)) part, but I have no idea of something else.
Edit In fact, it seems to be the arg.n >2 that is not efficient...
function pgcd ( ... )
local arg = table.pack(...)
if arg.n >2
then
local tmp = table.remove(arg,1)
return pgcd (tmp, pgcd( unpack(arg) ))
else
a,b = unpack(arg)
repeat
a , b = b , a % b
until a % b == 0
return b
end
end
print (pgcd(18,12)) -- works fine
print (pgcd(18,12,9)) -- everlasting loop
In fact the endding test was testing once too far.
function pgcd ( ... )
local arg = table.pack(...)
if arg.n > 2
then
local tmp = table.remove(arg,1)
return pgcd (tmp, pgcd( unpack(arg) ) )
else
a,b = unpack(arg)
repeat
a , b = b , math.fmod(a,b)
until b == 0 -- test was once too far
return a
end
end
print (pgcd(18,12)) -- works fine
print (pgcd(18,12,6)) -- works fine
In the following recorded plot, I cannot find the instruction that constructs the layout and sets the par() settings before the first plot.new call()
library( PerformanceAnalytics )
data( managers )
# write the plot to the open device
suppressWarnings(charts.RollingRegression(managers[, 1:6], managers[, 8, drop=FALSE], Rf = .04/12, colorset = rich6equal, legend.loc="topleft"))
# record = investigate the primitive calls. notice no par() nor layout() before the first call to plot.new()
recorded = recordPlot()
lapply(recorded[[1]], "[[", 1 )
# as a result, the following creates one plot per page, not 3 on the same page:
lapply( recorded[[ 1 ]] , function( x ) { do.call( x[[ 1 ]] , as.list( x[[ 2 ]] ) ) } )
Perhaps this is encoded in recorded[[ 2 ]] which looks like some kind of encoded raw data? If so, how could I grab the insructions prior to the first plot.new() from the raw data?
Edit
Warning: dirty hack.
If you want to encode the initial state in the instruction list, here's how:
tryCatch( dev.off() , error = function( e ) {} )
plot.new()
par( new = TRUE )
originalLayoutFunction = graphics:::layout
graphicsEnvironment = as.environment( "package:graphics" )
newLayoutFunction = function( ... )
{
originalLayoutFunction( ... )
par( mfg = c( 1 , 1 ) )
}
unlockBinding( "layout" , env = graphicsEnvironment )
assign( "layout" , newLayoutFunction , envir = graphicsEnvironment )
lockBinding( "layout" , env = graphicsEnvironment )
tryCatch( YOUR_PLOT_CALL_HERE , finally =
{
unlockBinding( "layout" , env = graphicsEnvironment )
assign( "layout" , originalLayoutFunction , env = graphicsEnvironment )
lockBinding( "layout" , env = graphicsEnvironment )
} )
recordedPlot = recordPlot()
dev.off()
You're probably right about what's in recorded[[2]]. My suspicion is that it contains the SEXP which "nicely hides the internals" referenced in this comment from the R sources:
/****************************************************************
* GEcreateSnapshot
****************************************************************
*/
/* Create a recording of the current display,
* including enough information from each registered
* graphics system to be able to recreate the display
* The structure created is an SEXP which nicely hides the
* internals, because noone should be looking in there anyway
* The product of this call can be stored, but should only
* be used in a call to GEplaySnapshot.
*/
A bit further down in the same file ($SRC_HOME/src/main/engine.c) is another possibly illuminating passage.
Like the comment above (and like the recordPlot help file), it too comes with a strongish admonition not to try mucking around with the objects stored by recordPlot(). "Here be dragons", they all say, and it looks like you are starting to meet them that were warned about ;)
/****************************************************************
* GEplaySnapshot
****************************************************************
*/
/* Recreate a saved display using the information in a structure
* created by GEcreateSnapshot.
*
* The graphics engine assumes that it is getting a snapshot
* that was created in THE CURRENT R SESSION
* (Thus, it can assume that registered graphics systems are
* in the same order as they were when the snapshot was
* created -- in patricular, state information will be sent
* to the appropriate graphics system.)
* [With only two systems and base registered on each device at
* creation, that has to be true: and grid does not save any state.]
*
* It also assumes that the system that created the snapshot is
* still loaded (e.g. the grid namespace has not been unloaded).
*
* It is possible to save a snapshot to an R variable
* (and therefore save and reload it between sessions and
* even possibly into a different R version),
* BUT this is strongly discouraged
* (in the documentation for recordPlot() and replayPlot()
* and in the documentation for the Rgui interface on Windows)
*/
What happens for a global variable when running in the parallel mode?
I have a global variable, "to_be_optimized_parameterIndexSet", which is a vector of indexes that should be optimized using gamultiobj and I have set its value only in the main script(nowhere else).
My code works properly in serial mode but when I switch to parallel mode (using "matlabpool open" and setting proper values for 'gaoptimset' ) the mentioned global variable becomes empty (=[]) in the fitness function and causes this error:
??? Error using ==> parallel_function at 598
Error in ==> PF_gaMultiFitness at 15 [THIS LINE: constants(to_be_optimized_parameterIndexSet) = individual;]
In an assignment A(I) = B, the number of elements in B and
I must be the same.
Error in ==> fcnvectorizer at 17
parfor (i = 1:popSize)
Error in ==> gamultiobjMakeState at 52
Score =
fcnvectorizer(state.Population(initScoreProvided+1:end,:),FitnessFcn,numObj,options.SerialUserFcn);
Error in ==> gamultiobjsolve at 11
state = gamultiobjMakeState(GenomeLength,FitnessFcn,output.problemtype,options);
E rror in ==> gamultiobj at 238
[x,fval,exitFlag,output,population,scores] = gamultiobjsolve(FitnessFcn,nvars, ...
Error in ==> PF_GA_mainScript at 136
[x, fval, exitflag, output] = gamultiobj(#(individual)PF_gaMultiFitness(individual, initialConstants), ...
Caused by:
Failure in user-supplied fitness function evaluation. GA cannot continue.
I have checked all the code to make sure I've not changed this global variable everywhere else.
I have a quad-core processor.
Where is the bug? any suggestion?
EDIT 1: The MATLAB code in the main script:
clc
clear
close all
format short g
global simulation_duration % PF_gaMultiFitness will use this variable
global to_be_optimized_parameterIndexSet % PF_gaMultiFitness will use this variable
global IC stimulusMoment % PF_gaMultiFitness will use these variables
[initialConstants IC] = oldCICR_Constants; %initialize state
to_be_optimized_parameterIndexSet = [21 22 23 24 25 26 27 28 17 20];
LB = [ 0.97667 0.38185 0.63529 0.046564 0.23207 0.87484 0.46014 0.0030636 0.46494 0.82407 ];
UB = [1.8486 0.68292 0.87129 0.87814 0.66982 1.3819 0.64562 0.15456 1.3717 1.8168];
PopulationSize = input('Population size? ') ;
GaTimeLimit = input('GA time limit? (second) ');
matlabpool open
nGenerations = inf;
options = gaoptimset('PopulationSize', PopulationSize, 'TimeLimit',GaTimeLimit, 'Generations', nGenerations, ...
'Vectorized','off', 'UseParallel','always');
[x, fval, exitflag, output] = gamultiobj(#(individual)PF_gaMultiFitness(individual, initialConstants), ...
length(to_be_optimized_parameterIndexSet),[],[],[],[],LB,UB,options);
matlabpool close
some other piece of code to show the results...
The MATLAB code of the fitness function, "PF_gaMultiFitness":
function objectives =PF_gaMultiFitness(individual, constants)
global simulation_duration IC stimulusMoment to_be_optimized_parameterIndexSet
%THIS FUNCTION RETURNS MULTI OBJECTIVES AND PUTS EACH OBJECTIVE IN A COLUMN
constants(to_be_optimized_parameterIndexSet) = individual;
[smcState , ~, Time]= oldCICR_CompCore(constants, IC, simulation_duration,2);
targetValue = 1; % [uM]desired [Ca]i peak concentration
afterStimulus = smcState(Time>stimulusMoment,14); % values of [Ca]i after stimulus
peak_Ca_value = max(afterStimulus); % smcState(:,14) is [Ca]i
if peak_Ca_value < 0.8 * targetValue
objectives(1,1) = inf;
else
objectives(1, 1) = abs(peak_Ca_value - targetValue);
end
pkIDX = peakFinder(afterStimulus);
nPeaks = sum(pkIDX);
if nPeaks > 1
peakIndexes = find(pkIDX);
period = Time(peakIndexes(2)) - Time(peakIndexes(1));
objectives(1,2) = 1e5* 1/period;
elseif nPeaks == 1 && peak_Ca_value > 0.8 * targetValue
objectives(1,2) = 0;
else
objectives(1,2) = inf;
end
end
Global variables do not get passed from the MATLAB client to the workers executing the body of the PARFOR loop. The only data that does get sent into the loop body are variables that occur in the text of the program. This blog entry might help.
it really depends on the type of variable you're putting in. i need to see more of your code to point out the flaw, but in general it is good practice to avoid assuming complicated variables will be passed to each worker. In other words anything more then a primitive may need to be reinitialized inside a parallel routine or may need have specific function calls (like using feval for function handles).
My advice: RTM