Output an absent optional enum in MiniZinc - minizinc

How does on output an optional enum?
enum Foo = { A, B };
var opt Foo: foo;
output [ "foo: \(foo)" ];
solve satisfy;
fails with this output:
Compiling test.mzn
MiniZinc: flattening error:
function _toString_Foo is used in output, par version needed
Finished in 29msec
If I change Foo to be a set of int
set of int: Foo = 1..2;
var opt Foo: foo;
output [ "foo: \(foo)" ];
solve satisfy;
then it works
Compiling test.mzn
Running test.mzn
foo: <>
----------
Finished in 136msec
And the missing value is clearly not a problem here.
Even if I check if the solution is present, it still fails
set of int: Foo = 1..2;
var opt Foo: foo;
output [ "foo: " ++
if (occurs(fix(foo))) then "present" else "absent" endif
];
solve satisfy;
That fails with
Compiling test.mzn
Running test.mzn
MiniZinc: evaluation error: undeclared identifier '_absent'
unknown file
Finished in 39msec
Actually, that even fails with a set of int.

UPDATE: The issue has been resolved on the develop branch of the MiniZinc compiler. In the next release, >2.1.6, it should be possible to use the optional parameters in the output.
Because enumerations are represented as integers in the solver input, special mapping functions are inserted into the output model to ensure the correct output.
Transforming the solver output into MiniZinc output is the task of the solns2out executable. This is done using an output model (.ozn).
The error you are getting is because the function required to map the integers back into the enumeration is not found, this is a bug in the compiler. Only two days ago the _toString_ function for sets of enumerations was added to the development branch and it seems the version for optional types is still missing.
I suggest you create an issue on GitHub and the issue will likely be resolved in the next MiniZinc release: https://github.com/MiniZinc/libminizinc/issues

Related

error: "struct" expression not at top level

function check(str,arg;type=DataType,max=nothing,min=nothing,description="")
#argcheck typeof(arg)==type
#argcheck arg>min
#argcheck arg<max
#argcheck typeof(description)==String
return arg
end
function constr(name,arg,field)
return :(function $name($arg,$field)
new(check($name,$arg,$field))
end)
end
macro creatStruct(name,arg)
code = Base.remove_linenums!(quote
struct $name
end
end)
print(arg)
append!(code.args[1].args[3].args,[constr(name,arg.args[1].args[1],arg.args[1].args[2])])
code
end
macro myStruct(name,arg)
#creatStruct name arg
end
#myStruct test12 (
(arg1,(max=10))
)
In my code above I'm trying to build a macro that Creates a struct, and within the struct, you can define an argument with boundaries (max, min) and description, etc.
I'm getting this error:
syntax: "#141#max = 10" is not a valid function argument name
and every time I'm trying to solve it, I get another error like:
LoadError: syntax: "struct" expression not at top level
So, I think my Code/Approach is not that cohesive. Anybody can suggest tips and/or another Approche.
You're attempting to make an argument name max with a default value of 10. The error is about max=10 not being a valid name (Symbol), while max is. The bigger issue is you're trying to put this in the struct expression instead of a constructor method:
struct Foo
bar::Float64
max::Int64
end
# constructor
Foo(bar, max=10) = Foo(bar, max)
So you have to figure out how to make an expression for a method with default values, too.
Your second error means that structs must be defined in the top-level. "Top-level" is like global scope but stricter in some contexts; I don't know the exact difference, but it definitely excludes local scopes (macro, function, etc). It looks like the issue is the expression returned by creatStruct being evaluated as code in myStruct, but the LoadError I'm getting has a different message. In any case, the error goes away if I make sure things stay as expressions:
macro myStruct(name,arg)
:(#creatStruct $name $arg)
end

What is meant by this SystemVerilog typedef enum statement?

typedef enum logic [1:0] {S0, S1, S2} statetype;
Does this statement mean that any variable declared as 'statetype' can only take three values, 2'b00, 2'b01, and 2'b10? If so, what happens if I assign the said variable with the value 2'b11?
The IEEE Std 1800-2017, section 6.19.3 Type checking, states:
Enumerated types are strongly typed; thus, a variable of type enum
cannot be directly assigned a value that lies outside the enumeration
set unless an explicit cast is used or unless the enum variable is a
member of a union. This is a powerful type-checking aid, which
prevents users from accidentally assigning nonexistent values to
variables of an enumerated type. The enumeration values can still be
used as constants in expressions, and the results can be assigned to
any variable of a compatible integral type.
Enumerated variables are type-checked in assignments, arguments, and
relational operators.
What I observe in practice is that some simulators issue a compile warning while others issue a compile error. You can see what happens on multiple simulators on edaplayground (if you sign up for a free account there).
For example, with VCS, the following code:
module tb;
typedef enum logic [1:0] {S0, S1, S2} statetype;
statetype s;
initial begin
s = S0;
$display("n=%s,s=%0d,", s.name(), s);
s = 3;
$display("n=%s,s=%0d,", s.name(), s);
end
endmodule
issues this warning:
Warning-[ENUMASSIGN] Illegal assignment to enum variable
tb.v, 16
tb, "s = 3;"
Only expressions of the enum type can be assigned to an enum variable.
The type int is incompatible with the enum 'statetype'
Expression: 3
Use the static cast operator to convert the expression to enum type.
but, it still runs the simulation and prints:
n=S0,s=0
n=,s=3
I believe the question should be rephrased to say that what is this is happening in our test-bench and how to avoid it. This will gives us more cleaner and bug free code.
efficient code to avoid the confusion:
typedef enum logic [1:0] {S0, S1, S2} statetype;
module top();
statetype st_e;
initial begin
for(int val=0;val<4; val++) begin
// casting for avoid confusion and gotchas
if (!$cast(st_e,val)) begin
$error("Casting not possible -> statetype:%0s and val:%0d",st_e,val);
end else begin
$display("statetype:%0s and val:%0d",st_e,val);
end
end
end
endmodule: top
This code is already there in edaplayground feel free to try it and update it. This could be replace with the sv macro for more efficiency. Please let me know I will provide the example for macros.
Output will be:
# run -all
# statetype:S0 and val:0
# statetype:S1 and val:1
# statetype:S2 and val:2
# ** Error: Casting not possible -> statetype:S2 and val:3
# Time: 0 ns Scope: top File: testbench.sv Line: 14
# exit

Xcode lldb error: can't print out Swift variable - get "$__lldb_injected_self.$__lldb_wrapped_expr_x" instead

Sometimes, when trying to print out a variable in the debugger, the following error message is displayed:
error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
var $__lldb_error_result = __lldb_tmp_error
~~~~^~~~~~~~~~~~~~~~~~~~
_
error: <EXPR>:18:5: error: use of unresolved identifier '$__lldb_injected_self'
$__lldb_injected_self.$__lldb_wrapped_expr_120(
^~~~~~~~~~~~~~~~~~~~~
This is a known lldb bug (https://bugs.swift.org/browse/SR-6156), but perhaps someone knows a workaround that can be used until that bug is fixed?
As a workaround you can print it in the lldb debugger using:
frame variable variablename
Also possible using shortened syntax for quicker typing
fr v variablename
Since XCode 10.2 an ever simpler lldb syntax is supported:
v variable
Update - new workarounds:
Print stack addresses:
v -L variablename
po like on stack frame variable.property
v -o variablename.property
Swift like p
e unsafeBitCast(address, to: ClassName.self)
Update2 - new workaround applicable for Swift classes being wrappers of objc classes.
Example:
v response
(HTTPURLResponse) response = 0x0000000283ba7640 {
if v works^:
e -l objc -- (int)[0x0000000283ba7640 statusCode]
(int) $2 = 404
Update 3
printing Swift arrays (here array of [Int])
v -L arrayName
0x00007ff7b753a9a8: ([Int]) arrayName = 1169 values {
0x000060000295e7b0: [0] = 1
...
then
e unsafeBitCast(0x00007ff7b753a9a8, to: UnsafeMutablePointer<Array<Int>>.self).pointee[0].bitWidth
also possible with map
e unsafeBitCast(0x00007ff7b753a9a8, to: UnsafeMutablePointer<Array<Int>>.self).pointee.map{ $0.bitWidth }
I'd appreciate reports what is actually helpful and works. Thanks.
More information on this kind of capabilities can be found here:
https://developer.apple.com/library/content/documentation/General/Conceptual/lldb-guide/chapters/C5-Examining-The-Call-Stack.html

OMShell returns String but doesn't recognize it

For one of my models, it is required to read the final value of all variables and set them as initial value for the next simulation. My real problem is due to types defined in OMShell. As can be seen in the scripting commands of OpenModelica, there are String type and "VariableName", "TypeName" types. To elaborate the difference:
// The following loads the Standard Modelica Library
>> loadModel(Modelica)
true
// The following throws an error
>> loadModel("Modelica")
The reason is that the loadModel function doesn't expect a string variable. It expects the name of the model. Returning my problem, I tried to use val function as in the following, so that I can give the value as the initial value of the next simulation.
>> final_time := 200;
>> myVarValue := val(myVar, final_time);
This can be done for each variable by using a for-loop, I thought as I have several variables and I realized the problem at this point.
// Get the list of all variables
>> myVarList := readSimulationResultVars(currentSimulationResult);
>> size(myVarList)
{724}
// The problem is that this list contains strings
>> myVarList[1]
"mySubSystem.myComponent.myPin.v"
// Following throws an error as it doesn't expect a string
>> val(myVarList[1], final_time)
How can I remove "" from the string that OMShell returns to me? I need to convert "myVar" to myVar so that I can use it as an input for the functions of OMShell.
You can use the stringVariableName function.
>>> vars:=OpenModelica.Scripting.readSimulationResultVars(currentSimulationResult)
{"r","time"}
>>> val(stringVariableName(vars[1]), 0.0)
1.0

How to return a value from a Python callback in Fortran using F2Py

Consider the following Fortran subroutine, defined in test.f:
subroutine test(py_func)
use iso_fortran_env, only stdout => output_unit
external py_func
integer :: a
integer :: b
a = 12
write(stdout, *) a
b = py_func(a)
write(stdout, *) b
end subroutine
Also the following Python code, defined in call_test.py:
import test
def func(x):
return x * 2
test.test(func)
Compiled with the following (Intel compiler):
python f2py.py -c test.f --fcompiler=intelvem -m test
I expect this as output when I run test:
12
24
But I actually get this:
12
0
It seems as if b is being initialised with a default value instead of the result of test. I have tried using the following in the Fortran:
!f2py intent(callback) py_func
external py_func
!f2py integer y,x
!f2py y = py_func(x)
But my program crashes after the printout of 12 to the console.
Any ideas what could be going on here? The reason for the crash would be a bonus, but I'm really just interested in getting a simple callback working at this point.
I don't claim to understand it, I found the answer on an F2Py forum thread. Adding integer py_func (not prefixed by !f2py) does the trick for me:
subroutine test(py_func)
use iso_fortran_env, only stdout => output_unit
!f2py intent(callback) py_func
external py_func
integer py_func
!f2py integer y,x
!f2py y = py_func(x)
integer :: a
integer :: b
a = 12
write(stdout, *) a
b = py_func(a)
write(stdout, *) b
end subroutine
Perhaps this is to do with space being needed for a temporary value used to store the result before being assigned to b? In any case, it is apparently compiler-dependent, which explains why it is not in various F2Py callback examples you can find elsewhere online.