Testing Multiple LTL Formulae with SPIN - model-checking

I have many LTL formulae that I am trying to test on the same .pml file. My issue is that when an error is found in any single ltl formula, the trail file is written (or overwrites) to the same trail file name. I have not been able to find a way to write to an trail file name of my choice. Does anyone know if this option exists?
If not, what is a strategy I could use for testing multiple ltl formulae from the same .pml file simultaneously without overwriting the same trail file every time?
I am aware of the SPIN runtime -x option, but that just prevents a trail file from being overwritten. It does not generate trail files with different names.

AFAIK, there is no such option.
WORKAROUND
For linux+bash, you can opt for the following, brutal, approach.
Define set_trail_name function:
~$ function set_trail_name() { sed -i "s/^\\(char \\*TrailFile =\\)\\(.*\\)$/\\1 \"${1}\";/" "${2}"; }
~$ export -f set_trail_name
It takes two parameters: your preferred trail_file_nime and the location of pan.c.
Then use it as follows:
~$ spin -a test.pml
ltl p1: [] (<> (! (q0)))
ltl p2: [] (<> (q1))
the model contains 2 never claims: p2, p1
...
~$ set_trail_name my_p1_name pan.c
~$ gcc -o pan pan.c
~$ ./pan -a -N p1
pan: ltl formula p1
pan:1: acceptance cycle (at depth 4)
pan: wrote my_p1_name.trail
...
~$ ls *.trail
my_p1_name.trail
~$ set_trail_name my_p2_name pan.c
~$ gcc -o pan pan.c
~$ pan -a -N p2
pan: ltl formula p2
pan:1: acceptance cycle (at depth 2)
pan: wrote my_p2_name.trail
...
~$ ls *.trail
my_p1_name.trail my_p2_name.trail
WORKAROUND IMPROVEMENT #1
You can go one step further, e.g.
#!/bin/bash
function set_trail_name() {
sed -i "s/^\\(char \\*TrailFile =\\)\\(.*\\)$/\\1 \"${1}\";/" "${2}";
}
function check_property() {
set -e
spin -a "${1}" 1>/dev/null
set_trail_name "${2}" pan.c
gcc -o pan pan.c
./pan -a -N "${2}"
set +e
}
check_property "${#}"
Which makes it easier to run it:
~$ ./run_spin.sh test.pml p1
pan: ltl formula p1
pan:1: acceptance cycle (at depth 4)
pan: wrote p1.trail
...
~$ ~$ ./run_spin.sh test.pml p2
pan: ltl formula p2
pan:1: acceptance cycle (at depth 2)
pan: wrote p2.trail
WORKAROUND IMPROVEMENT #2
You can even go a couple of steps further, e.g.
#!/bin/bash
function set_trail_name()
{
sed -i "s/^\\(char \\*TrailFile =\\)\\(.*\\)$/\\1 \"${1}\";/" "${2}";
}
function check_property()
{
echo -e "\\n>>> Testing property ${1} ...\\n"
set_trail_name "${1}" pan.c
gcc -o pan pan.c
./pan -a -N "${1}"
}
function check_properties()
{
set -e
spin -a "${1}" 1>/dev/null
mapfile -t properties < <(gawk 'match($0, /^ltl ([^{]+) .*$/, a) { print a[1] }' "${1}")
for prop in "${properties[#]}"
do
check_property "${prop}"
done
set +e
}
check_properties "${#}"
Which makes it trivial to run it:
~$ ./run_spin.sh test.pml
>>> Testing property p1 ...
pan: ltl formula p1
pan:1: acceptance cycle (at depth 4)
pan: wrote p1.trail
...
>>> Testing property p2 ...
pan: ltl formula p2
pan:1: acceptance cycle (at depth 2)
pan: wrote p2.trail
...
NOTES
You might want to enrich the scripts with
cleanup of temporary files, e.g. pan, pan.*, _spin_nvr.tmp
analysis of property status (true/false) and printing
...
Another completely legitimate solution could be to simply rename existing trail files after each call to the Spin model checker.

Related

Check a c file output in Linux

I have 2 files .c which only contain a printf("x")
I am in bash script and i want to check if the values in the printf are for project1.c =20 and for project 2 =10,and then make some changes depending on the values.
How am i supposed to make the comparison in the if command?
This is what i have tried to do,not sure if it is right way.
for d in $1/*/*
do
gcc project1 project1.c
if[ ./project1 = 20 ];then
$project1 =30
else
$project1 =0
fi
gcc project2 project2.c
if[ ./project2 =10 ];then
$project2 = 70
else
$project2 = 0
fi
sum=$project1 + $project2
echo "project1 : $project1 project2: $project2 total grade: $sum" >> grades.txt
done
fi
Your invocation of gcc is wrong. You have to specify the output file:
gcc -o project1 project1.c
Next, in shell, variable substitution is a different process than assignment. So, you can't write $var=foo. The correct syntax is var=foo.
Then, space is a special character (it is used to separate arguments). So var=foo is not the same than var = foo. So, the correct syntax is:
project1=30
Next, in shell, the pattern $(command) is replaced by the result of command. So. I have to do:
if [ $(./project2) == 10 ]; then
Finally, you can do arithmetic using $((calculus)). So, you have to write:
sum=$(($project1 + $project2))

fish shell: unable to erase function

When trying to temporarily disable a fish_mode_prompt function:
function get_input -a prompt var_name -d 'get user input and place it in var_name'
functions -c fish_mode_prompt fish_mode_prompt_tmp
functions -e fish_mode_prompt
read --global --prompt-str="$prompt" $var_name
functions -c fish_mode_prompt_tmp fish_mode_prompt
functions -e fish_mode_prompt_tmp
end
I get the following error:
functions: Function “fish_mode_prompt” already exists. Cannot create copy “fish_mode_prompt_tmp”
~/.config/fishdots/plugins/fishdots_crm/init/rc1.d/01.functions.fish (line 114):
functions -c fish_mode_prompt_tmp fish_mode_prompt
^
in function “get_input”
called on standard input
with parameter list “hello world: charlie”
functionsfunctions - print or erase functions
-
Synopsis
functions [ -a | --all ] [ -n | --names ]
functions [ -D | --details ] [ -v ] FUNCTION
functions -c OLDNAME NEWNAME
functions -d DESCRIPTION FUNCTION
functions [ -e | -q ] FUNCTIONS...
functions: Type “help functions” for related documentation
I'm not entirely sure what's happening here. Should this work?
See https://github.com/fish-shell/fish-shell/issues/741. functions --erase does not actually remove the file containing the autoloaded function definition.
Rather than attempt to rename the function in that fashion just replace it with a dummy implementation:
function fish_mode_prompt; end
read --global --prompt-str="$prompt" $var_name
function -e fish_mode_prompt
But I don't understand why you would want to do this. If you're using vi mode you really should just let its state indicator be present at all times. Even when executing a read command. If you dislike the state indicator I would simply define your own ~/.config/fish/functions/fish_mode_prompt.fish autoloaded script with an empty fish_mode_prompt function.

Processing text in bash - extracting the volume of a program from pactl sink-inputs output

Looking for a way to extract the volume from
pactl list sink-inputs
Output example:
Sink Input #67
Driver: protocol-native.c
Owner Module: 12
Client: 32
Sink: 0
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"s16le\"" format.channels = "2" format.rate = "44100" format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 19661 / 30% / -31.37 dB, front-right: 19661 / 30% / -31.37 dB
balance 0.00
Buffer Latency: 100544 usec
Sink Latency: 58938 usec
Resample method: n/a
Properties:
media.name = "'Alerion' by 'Asking Alexandria'"
application.name = "Clementine"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "32"
media.role = "music"
application.process.id = "16924"
application.process.user = "gray"
application.process.host = "gray-kubuntu"
application.process.binary = "clementine"
application.language = "en_US.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "54f542f950a5492c9c335804e1418e5c"
application.process.session_id = "3"
application.icon_name = "clementine"
module-stream-restore.id = "sink-input-by-media-role:music"
media.title = "Alerion"
media.artist = "Asking Alexandria"
I want to extract the
30
from the line
Volume: front-left: 19661 / 30% / -31.37 dB, front-right: 19661 / 30% / -31.37 dB
Note: There may be multiple sink inputs, and I need to extract the volume only from Sink Input #67
Thanks
P.S. Need this for a script of mine which should increase or decrease the volume of my music player. I'm completely new to both linux and bash so I couldn't figure a way to resolve the problem.
Edit:
My awk version
gray#gray-kubuntu:~$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
Since you are pretty new to use standard text processing tools, I will provide an answer with a detailed explanation. Feel free to use it for future.
Am basing this answer using the GNU Awk I have installed which should likely also work in mawk installed in your system.
pactl list sink-inputs | \
mawk '/Sink Input #67/{f=1; next} f && /Volume:/{ n=split($0,matchGroup,"/"); val=matchGroup[2]; gsub(/^[[:space:]]+/,"",val); gsub(/%/,"",val); print val; f=0}'
Awk processes one line at a time which is based on a /pattern/{action1; action2} syntax. In our case though, we match the line /Sink Input #67/ and enable a flag(f) to mark the next occurrence of Volume: string in the lines below. Without the flag set it could match the instances for other sink inputs.
So once we match the line, we split the line using the de-limiter / and get the second matched element which is stored in the array(matchGroup). Then we use the gsub() calls twice once, to replace the leading white-spaces and other to remove the % sign after the number.
This script I wrote might be what you wanted. It lets me adjust the volume easily using the pacmd and pactl commands. Seems to work well when I'm using a GNOME desktop, (Wayland or Xorg), and it's working on RHEL/Fedora and Ubuntu so far. I haven't tried using it with other desktops/distros, or with surround sound systems, etc.
Drop it in your path, and run it without any values to see the current volume. Alternatively set the volume by passing it a percentage. A single value sets both speakers, two values will set left, and right separately. In theory you shouldn't use a value outside of 0%-200%, but the script doesn't check for that (and neither does PulseAudio apparently), so be careful, as a volume higher than 200% may harm your speakers.
[~]# volume
L R
20% 20%
[~]# volume 100% 50%
[~]# volume
L R
100% 50%
[~]# volume 80%
[~]# volume
L R
80% 80%
#!/bin/bash
[ ! -z "$1" ] && [ $# -eq 1 ] && export LVOL="$1" && export RVOL="$1"
[ ! -z "$1" ] && [ ! -z "$2" ] && [ $# -eq 2 ] && export LVOL="$1" && export RVOL="$2"
SINK=$(pacmd list-sinks | grep -e '* index:' | grep -Eo "[0-9]*$")
if [ -z "$LVOL" ] || [ -z "$RVOL" ]; then
# pacmd list-sinks | grep -e '* index:' -A 20 | grep -e 'name:' -e '^\s*volume:.*\n' -e 'balance' --color=none
printf "%-5s%-4s\n%-5s%-4s\n" "L" "R" $(pacmd list-sinks | grep -e '* index:' -A 20 | grep -e '^\s*volume:.*\n' --color=none | grep -Eo "[0-9]*%" | tr "\n" " " | sed "s/ $/\n/g")
exit 0
elif [[ ! "$LVOL" =~ ^[0-9]*%$ ]] || [[ ! "$RVOL" =~ ^[0-9]*%$ ]]; then
printf "The volume should specified as a percentage, from 0%% to 200%%.\n"
exit 1
elif [ "$SINK" == "" ]; then
printf "Unable to find the default sound output.\n"
exit 1
fi
pactl -- set-sink-volume $SINK $LVOL $RVOL

Two way communication with process

I have given some compiled program. I want to communicate with it from my bash script by program stdin and stdout. I need two way communication. Program cannot be killed between exchange of information. How I can do that?
Simple example:
Let that program be compiled partial summation (C++) and script results will be squares of that sums. Program:
int main() {
int num, sum = 0;
while(true) {
std::cin >> num;
sum += num;
std::cout << sum << std::endl;
}
}
My script should looks like that:
for i in 1 2 3 4; do
echo "$i" > program
read program to line;
echo $((line * line))
done
If in program I have for(int i = 1; i <= 4; ++i), then I can do something like that:
exec 4< <(./program); # Just read from program
for i in 1 2 3 4; do
read <&4 line;
echo "sh: $((line * line))";
done
For more look here. From the other hand, if in program I have std::cout << sum * sum;, then solution could be:
exec &3> >(./program); # Write to program
for i in 1 2 3 4; do
echo "$i" > &3
done
My problem is two way communication with other process / program. I don't have to use exec. I cannot install third party software. Bash-only solution, without files, will be nice.
If I run other process, it will be nice to know pid to kill that at the end of script.
I think about communication with two or maybe three processes in the future. Output of firs program may dependents on output of second program and also in second side. Like communicator of processes.
However, I cannot recompile programs and change something. I have only stdin and stdout communication in programs.
If you have bash which is newer than 4.0, you can use coproc.
However, don't forget that the input/output of the command you want to communicate might be buffered.
In that case you should wrap the command with something like stdbuf -i0 -o0
Reference: How to make output of any shell command unbuffered?
Here's an example
#!/bin/bash
coproc mycoproc {
./a.out # your C++ code
}
# input to "std::cin >> num;"
echo "1" >&${mycoproc[1]}
# get output from "std::cout << sum << std::endl;"
# "-t 3" means that it waits for 3 seconds
read -t 3 -u ${mycoproc[0]} var
# print it
echo $var
echo "2" >&${mycoproc[1]}
read -t 3 -u ${mycoproc[0]} var
echo $var
echo "3" >&${mycoproc[1]}
read -t 3 -u ${mycoproc[0]} var
echo $var
# you can get PID
kill $mycoproc_PID
output will be
1
3
6
If your bash is older than 4.0, using mkfifo can do the same thing like:
#!/bin/bash
mkfifo f1 f2
exec 4<> f1
exec 5<> f2
./a.out < f1 > f2 &
echo "1" >&4
read -t 3 -u 5 var
echo $var
rm f1 f2
Considering that your C++ program reads from standard output, and prints to standard output, it's easy to put it inside a simple chain of pipes:
command_that_writes_output | your_cpp_program | command_that_handle_output
In your specific case you probably need to modify the program to only handle one single input and writing one single output, and remove the loop. Because then you can do it very simple, like this:
for i in 1 2 3 4; do
result=`echo $i | ./program`
echo $((result * result))
done

prstat in Ubuntu or Centos

As the Java Performance said:
Solaris prstat has additional capabilities
such as reporting both user and kernel or system CPU utilization along with other
microstate information using the prstat -m and -L options. The -m option prints
microstate information, and -L prints statistics on per lightweight process.
There is any tool available like prstat in Centos or Ubuntu ?
I believe the Linux commands you are looking for are top and pstree .
Here is ptree for Linux,
#!/bin/sh
# Solaris style ptree
[ -x /usr/bin/ptree ] && exec /usr/bin/ptree "$#"
# Print process tree
# $1 = PID : extract tree for this process
# $1 = user : filter for this (existing) user
# $1 = user $2 = PID : do both
PATH=/bin:/usr/bin:/usr/sbin:/sbin
export PATH
psopt="-e"
case $1 in
[a-z]*) psopt="-u $1";shift;;
esac
[ -z "$1" ] &&
exec ps $psopt -Ho pid=,args=
#some effort to add less to the ps list
tmp=/tmp/ptree.$$
trap 'rm $tmp' 0 HUP INT TERM
ps $psopt -Ho pid=,args= >$tmp
<$tmp awk '
{ ci=index(substr($0,7),$2); o[ci]=$0 }
ci>s[a] { s[++a]=ci }
$1==pid {
for(i=1;i<=a;i++) {
si=s[i]; if(si<=ci) print o[si]
}
walkdown=ci
next
}
ci<walkdown { exit }
walkdown!=0 { print }
' pid="$1"
There is no prstat "equivalent" tool in Linux. You can use a combination of top and ps (or /proc/$pid/ resources) to get some useful result; maybe writing a shell script (using grep, sed and awk) which collects results from above commands and files.
Just for reference I found this link about top command and kernel, user and idle CPU utilization intresting
http://blog.scoutapp.com/articles/2015/02/24/understanding-linuxs-cpu-stats
Hope this helps.

Resources