How to write symbols to file in scilab - matlab

I'm working on symbolic toolkit. Trying to solve some equations and that's a long string of symbols such as x= a1+a2^3+b0*b1... upto 80,000(80k) characters.
So I needed to put that in file.
mputstr() ans other wrting functions are not working since they are symbols.
Error is thrown as: not a string or specified format.
Does any method can help to bring down the variable to file.
code is :
Syms aa ab ac
z=ab^6*ac^6*ad^3*ba^3*bg^3*bh^3+3*aa^4*ab^6*ac^6*ad^4*ba^4*bg^2*bh^2+3*aa^5*ab^6*ac^6*ad^5*ba^5*bg*bh+aa^6*ab^6*ac^6*ad^6*ba^6
mputstr({char(z)},fd)
>>error 10000
>>char: Wrong type for input argument: Cell expected.
at line 95 of function char called by :
mputstr(z,fd)
>> !--error 999
>mputstr: Wrong type for input argument #1: A string expected.
p=string(z)
mputstr(p,fd)
>>!--error 999
>mputstr: Wrong type for input argument #1: A string expected.
mfprintf("%s",z)
>> !--error 246
>>Function not defined for given argument type(s),
check arguments or define function %c_mfprintf for overloading. ..

Let's say you have a symbolic equation x:
syms a b c
x = a + b * c
Here, x denotes a symbolic variable, so you cannot directly write it to a file. You need to convert it to a character array first. So you should be using something like
fd = mopen( this_file, "wt" );
mputstr( char(x), fd );
mclose( fd );

I think that #bremen_matt's answer is the good one, but with a modification.
If your "Syms" variables are something complex so char() and string() cannot be used, why you are not creating your own conversion function?
Please, see below my modification of #bremen_matt example:
syms a b c
x = a + b * c
fd = mopen( this_file, "wt" );
mputstr( syms_to_string(x), fd );
mclose( fd );
The syms_to_string() is returning a string of the information that you would like to print of the symbol x, and same function could be used to print other symbols (e.g. a). Of course, the syms_to_string() function could be better defined using overloading.

Related

passing varargin to subfunction if string

I want to modify function rand and define my own function
function num = rand(varargin)
Most of the time, i just wrap the invocation
num = builtin("rand", [varargin{:}]);
and this works well except in case there is a string argument.
For rand(2,3,"double") I obtain
warning: implicit conversion from numeric to char
warning: called from rand at line 83 column 11
error: rand: unrecognized string argument
error: called from rand at line 83 column 11
and for rand("seed",2) the same.
ON the other hand, rand("seed") seems to work fine.
Can anyone offer an explanation and a solution?
The syntax:
num = builtin('rand', [varargin{:}]);
Will only work for you in cases where the input arguments can be represented as either a comma-separated list or a vector, such as when you specify a size for rand:
num = rand(2, 3, 4);
% Or ...
num = rand([2 3 4]);
It will not work for inputs that must be entered separately, like so:
num = rand(2, 3, 'double'); % Works
num = rand([2 3 'double']); % Throws an error
In general, you should just pass the contents of varargin as a comma-separated list (without collecting the contents into a vector/matrix) since builtin is designed to handle that just fine:
num = builtin('rand', varargin{:});
Also, be mindful of the difference between "strings" like 'rand' (a character array) and "rand" (a string). They can have different behavior in certain cases.

Reversing the variable assignments in MATLAB

If I have a string "x1 = chyl_gi", where x1 and chyl_gi are both defined as symbolic variables, then the statement can be evaluated.
Typing in x1 will result in the value chyl_gi being returned.
Typing in chyl_gi will result in chyl_gi being returned.
How do I change the evaluation of "x1 = chyl_gi" so that typing in chyl_gi will result in returning x1? I can't change the order in how the variables are typed since I am working with a large text file in this format :
x1 = some var
x2 = another var
...
Now knowing your intended use, I recommend to use the subs function. Start parsing your text file to get the mapping:
syms x1 x2 chyl_gi chyl_gj a b c
mapping={x1,chyl_gi;x2,chyl_gj} %represents x1=chyl_gi and x2=chyl_gj;
And some example expression:
expr=x1+chyl_gi*(a+b+c);
Now you can simply use the subs function:
subs(expr,mapping,mapping(:,2:-1:1));
Which returns:
chyl_gi + x1*(a + b + c)
The advantage over the example in my comment above is, that you are really using the symbolic engine here.

How do I use MATLAB's inputParser with optional string inputs? The documentation says "use a validation function" but it's unclear how to do that

I have a MATLAB file that contains a single top-level function, called sandbox. That function in turn contains two nested functions, mysum and myprod, which are identical in functionality and what parameters they allow except that one uses #sum internally and the other uses #prod internally. My goal is to create a wrapper function to use in both mysum and myprod that takes care of all the validation and input parsing. This function is called applyFunc.
Here's where it gets tricky. mysum and myprod come in two forms:
mysum(v) returns sum(v, 1).
mysum(v, 'imag') returns sum(v, 1) + 1i
Any other combinations of input should throw an error.
I'm having trouble using inputParser to parse these various combinations of input, specifically the optional string input. Here's the code:
function sandbox()
%% Data
v = [1 4; 3 3];
%% Calculations
s = mysum(v);
si = mysum(v, 'imag');
p = myprod(v);
pi = myprod(v, 'imag');
%% Accuracy tests
assert(isequal(s, [4 7]))
assert(isequal(si, [4+1i 7+1i]))
assert(isequal(p, [3 12]))
assert(isequal(pi, [3+1i 12+1i]))
function x = mysum(varargin)
x = applyFunc(#sum, varargin{:});
end
function x = myprod(varargin)
x = applyFunc(#prod, varargin{:});
end
end
function x = applyFunc(func, varargin)
p = inputParser();
p.addRequired('func', #(x) validateattributes(x, {'function_handle'}, {'scalar'}));
p.addRequired('v', #(x) validateattributes(x, {'double'}, {}, 'applyFunc:msg', 'v'));
p.addOptional('imag', '', #(x) validatestring(x, {'imag', ''})); % THIS LINE IS THE PROBLEM
p.parse(func, varargin{:});
f = p.Results.func;
v = p.Results.v;
strflag = p.Results.imag;
x = f(v);
if ~isempty(strflag)
validatestring(strflag, {'imag'});
x = x + 1i;
end
end
The line that's causing the problem is this one (as marked in the code above):
p.addOptional('imag', '', #(x) validatestring(x, {'imag', ''}));
The documentation for inputParser says that:
For optional string inputs, specify a validation function. Without a validation function, the input parser interprets valid string inputs as invalid parameter names and throws an error.
Unfortunately I don't have any idea how to do this. Is there something simple Im missing or what? If the 'imag' argument isn't passed at all (as in the assignment of s and p), the code works fine, but if I do pass it, I get this error:
Error using sandbox>applyFunc (line 32)
The value of 'imag' is invalid. It must satisfy the function:
#(x)validatestring(x,{'imag',''}).
Error in sandbox/mysum (line 18)
x = applyFunc(#sum, varargin{:});
Error in sandbox (line 7)
si = mysum(v, 'imag');
Any help?
The problem is that validatestring returns the matching string from the cell argument ({'imag',''}) rather than a Boolean indicating if it passes validation. Instead, use strcmp and any:
#(x) any(strcmp(x,{'imag', ''}))
Also, with validatestring, if the input string did not match either 'imag' or '' (actually just 'imag' since empty strings only match in R2014a+), it would throw an error rather than returning false so that the inputParser could return the appropriate error.
Another nice way to fix the problem is to change the syntax of applyFunc entirely so that instead of just 'imag' as an optional string input argument, use a Parameter-Value with 'imag' as the parameter and a validated boolean as the input.
The input definition suggested by Amro in the comments:
p.addParameter('imag', false, #(x)validateattributes(x, {'logical'}, {'scalar'}))
The usage:
mysum(x,'imag',true)
mysum(x) % default is equivalent to mysum(x,'imag',false)
This would simplify the rest of the code with p.Result.imag being a logical scalar. I would suggest:
x = f(v) + p.Result.imag*1i;
The problem is not inputParser, I think the issue is with validatestring.
1) First it does not match on empty strings:
>> x = ''
x =
''
>> validatestring(x, {'imag',''})
Expected input to match one of these strings:
imag,
The input did not match any of the valid strings.
Caused by:
Error using validatestring>checkString (line 85)
Expected input to be a row vector.
2) Second, if it successfully matches, it returns the resolved string (from one of the valid choice), instead of true/false. inputParser requires that the validation function either return a boolean, or nothing but throws error on failure.

How to declare a function with an argument which is an array?

I need to declare a function that has 32 arguments, so it would be handy to put an unique argument: an array of 32 elements.
I don't find the syntax to do that, I've tried everythinh like:
function x=myfunction(str(32)) (etc...)
But without success.
Unlike other languages, MATLAB can accept matrices as a single argument; so you could just check that the input argument is a vector of length 32:
function x = myfunction(arg)
if length(arg) ~= 32
error('Must supply 32 arguments!');
end
%# your code here
end
If it's a variable number of arguments, check out varargin:
function x = myfunction(varargin)
But for 32 arguments, consider using an input structure:
function x = myfunction(argStruct)
if length(fieldnames(argStruct)) ~= 32
error('not enough arguments!');
end
Supply arguments in the structure, then pass the structure:
>> myArgs = struct();
>> myArgs.arg1 = 5;
>> myArgs.arg2 = 7;
>> %#(etc)
>> x = myfunction(myArgs);
Then in the function, you could either call argStruct.arg1, etc, directly; or unpack it into 32 different variables inside the function. I would give the fields descriptive names so you don't refer to them as arg1, etc inside your function. For that many input arguments, people using the function probably won't remember the order in which your function requires them to pass inputs to. Doing it with a struct lets users pass in arguments without needing to think about what order those inputs are defined.
To add to #strictlyrude27's awesome answer, it looks like you may misunderstand how function declarations work in Matlab. You wrote:
function x=myfunction(str(32))
However, you don't need to declare the type of input in matlab. Just give it a name, and then use it. So, the proper syntax for a declaration would be:
function x = myfunction(myInput)

MATLAB: If Statement inside loop is not executing, nor printing to the screen

So, we are trying to execute the following code. The two if statements are executing, however, the inside if statements are failing to execute (we verified this by not suppressing the output). Is there a reason why? Or are we just not able to reach this state?
Specifications
The input is as follows: v is a vector of int values and c is a integer. c must be less than or equal to one of the values within v
The problem that we are trying to solve with this algorithm is as follows:
Given a cash register, how does one make change such that the fewest coins
possible are returned to the customer?
Ex: Input: v = [1, 10, 25, 50], c = 40. Output O = [5, 1, 1, 0]
We are just looking for not a better solution but more of a reason why that portion of the code is not executing.
function O = changeGreedy(v,c)
O = zeros(size(v,1), size(v,2));
for v_item = 1:size(v,2)
%locate largest term
l_v_item = 1
for temp = 2:size(v,2)
if v(l_v_item) < v(temp)
l_v_item = temp
end
end
%"Items inside if statement are not executing"
if (c > v(l_v_item))
v(l_v_item) = -1 %"Not executing"
else
O(l_v_item) = idivide(c, v(l_v_item)) %"Not executing"
c = mod(c, v(l_v_item)) %"Not executing"
end
end
If c or v are not integers, i.e. class(c) evaluates to double, then I get the following error message
??? Error using ==> idivide>idivide_check at 66
At least one argument must belong to an integer class.
Error in ==> idivide at 42
idivide_check(a,b);
and the program stops executing. Thus, the inside of the second statement never executes. In contrast, if, say, c is an integer, for example of class uint8, everything executes just fine.
Also: what are you actually trying to achieve with this code?
Try to do this operation on your input data:
v = int32([1, 10, 25, 50]), c = int32(40)
and run again, at least some portions of your code will execute. There is an error raised by idivide, which apparently you missed:
??? Error using ==> idivide>idivide_check at 67
At least one argument must belong to an integer class.
Error in ==> idivide at 42
idivide_check(a,b);
Indeed, idivide seems to require that you have actual integer input data (that is, class(c) and class(v) both evaluate to an integer type, such as int32).