Rule conjI to split all the terms - isabelle

The rule conjI splits a conjunction as follows:
show "A ^ B ^ C ^ D"
proof(rule conjI)
show "A" sorry
next
show "C ^ D" sorry"
Is there any rule that splits all the terms connected by the conjunction? Some like:
show "A ^ B ^ C ^ D"
proof(rule ?)
show "A" sorry
next
show "C" sorry"
next
show "D" sorry"

You can't do that with a single rule application, but you can do intro conjI to apply it exhaustively.
There's also the method safe that does a variety of things like this (split products, apply appropriate introduction/elimination rules etc).

Related

Keep text between 2nd dash and first flash in R

I have a vector of strings that look like this:
a - bc/def_g - A/mn/us/ww
opq - rs/ts_uf - BC/wx/yza
Abc - so/dhie7u - XYZ/En/xy/jkq - QWNE
I'd like to get the text after 2nd dash (-) but before first flash (/), i.e. the result should look like
A
BC
XYZ
What is the best way to do it (the vector has more than 500K rows.)
Thanks
Suppose your string is defined like this:
string <- c("a - bc/def_g - A/mn/us/ww",
"opq - rs/ts_uf - BC/wx/yza",
"Abc - so/dhie7u - XYZ/En/xy/jkq - QWNE")
Then you can use sub
> sub(".*\\-\\s+([A-Z]+)/.*", "\\1", string)
[1] "A" "BC" "XYZ"
See regex in use here
^[^-]*-[^-]*-\s*\K[^/]+
^ Assert position at the start of the line
[^-]* Match any character except - any number of times
- Match this literally
[^-]* Match any character except - any number of times
- Match this literally
\s* Match any number of whitespace characters
\K Resets the starting point of the pattern. Any previously consumed characters are no longer included in the final match
[^/]+ Match any character except / one or more times
Alternatively, as suggested by Jan in the comments below (I believe it has since been deleted) ^(?:\[^-\]*-){2}\s*\K\[^/\]+ may be used. It's shorter and easily scalable, but more adds steps.
See code in use here
x <- c("a - bc/def_g - A/mn/us/ww", "opq - rs/ts_uf - BC/wx/yza", "Abc - so/dhie7u - XYZ/En/xy/jkq - QWNE")
m <- regexpr("^[^-]*-[^-]*-\\s*\\K[^/]+", x, perl=T)
regmatches(x, m)
Result: [1] "A" "BC" "XYZ"

Access elements of data types

Is it possible in Isabelle to access the individual elements of a data type? Let's say I have the following data type:
datatype foo = mat int int int int
and (e.g. in a lemma)
fixes A :: foo
Is it possible to access the single elements of A? Or alternatively, fix the single elements (fix a b c d :: int) and then define A as mat a b c d?
Alternatively it is possible to define custom extractor functions when specifying a data type. In your case, for example
datatype foo = Mat (mat_a : int) (mat_b : int) (mat_c : int) (mat_d : int)
would work.
Then you can access the first element of a foo value x by mat_a x, the second by mat_b x, and so on.
Example:
value "mat_a (Mat 1 2 3 4)"
"1" :: "int"
On a logical level, you can use the case syntax to deconstruct the datatype (i.e. case A of mat a b c d ⇒ …). You can also define your own projection functions using fun or primrec, e.g.
primrec foo1 where "foo1 (mat a b c d) = a"
In a proof, you can access the values using obtain and the cases command, e.g.
obtain a b c d where "A = mat a b c d" by (cases A) auto
As for your questions about definitions, you can make local definitions in Isar proofs like this:
define A where "A = mat a b c d"
and you can then unfold that definition using the theorem A_def.
If you want to use your definition in the premises or goal already (and have it unfolded in the theorem after proving it), you can use defines:
lemma
defines "A ≡ mat a b c d"
shows …
Again, this gives you a fact A_def that you can use to unfold the definition.
You can also use let ?A = mat a b c d or pattern matching with is to introduce abbreviations. In contrast to the definitions from before, these are only on the syntactic level, i.e. you type ?A, but after parsing, you have mat a b c d, and you will also see mat a b c d in the output. is works like this:
lemma
shows "P (mat a b c d)" (is "P ?A")
proof -
term ?A
It also works after "assumes".

R - replacing strings using gsub()

I have a lot of unclean data in the form:
abc
abc/def
abc/de
abc/d
abc/def/i j k
abc/def/i
abc/def/i j
This is just the part of the data I would like to change. This is part of much bigger set of data.
I would like to change all the elements to abc/def/i j k.
I have used the gsub() function as follows:
gsub('abc[a-z/]', 'abc/def/i j k', str)
output :
abc/def/i j k
abc/def/i j k/def
abc/def/i j k/de
abc/def/i j k/d
The problem being that it replaces any occurrence of the pattern.
The only solution where i got decent enough results are where i hard code all the possible options like this:
gsub('abc$|abc/d$|abc/de$|abc/def/i$', 'abc/def/i j k', str)
However, this would not work if there is a variation in any new data.
So I was wondering if it was possible to get the result without hard coding the parameters.
You may use
x <- c("abc", "abc/def","abc/de","abc/d","abc/def/i j k","abc/def/i","abc/def/i j")
sub("^(abc)(?:/[^/]*)?", "\\1/def", x)
## => [1] "abc/def" "abc/def" "abc/def" "abc/def"
## [5] "abc/def/i j k" "abc/def/i" "abc/def/i j"
See R demo
Details:
^ - start of string
(abc) - Group 1: abc
(?:/[^/]*)? - an optional group matching a sequence of:
/ - a /
[^/]* - 0+ chars other than /

Understanding how to pass macro arguments to a program in Stata

I am currently writing a short program to print the global macro variables of the current Stata session.
I cannot understand the outcome of the following piece of code:
macro drop _all
global glob0: all globals
cap program drop print_globals
program define print_globals
args start_globs
di "$glob0"
di "`start_globs'"
end
print_globals $glob0
The outcome of this is:
S_level S_ADO S_StataMP S_StataSE S_FLAVOR S_OS S_OSDTL S_MACH
S_level
Why am I not passing to start globs the entire information contained in glob0?
Your args statement assigns only the first argument supplied to the program to a local macro; if there are other arguments they are ignored.
The essence of the matter is whether double quotes are used to bind what is supplied into one argument.
Whether you supply an argument as a global or a local is immaterial: globals and locals mentioned on the command line are evaluated before the program even runs and are not seen as such; only their contents are passed to the program.
Define this simpler program and run through the possibilities:
program showfirstarg
args first
di "`first'"
end
global G "A B C D E"
local L "A B C D E"
showfirstarg $G
showfirstarg "$G"
showfirstarg `L'
showfirstarg "`L'"
Results in turn:
. showfirstarg $G
A
. showfirstarg "$G"
A B C D E
. showfirstarg `L'
A
. showfirstarg "`L'"
A B C D E
In order to print the content of the program argument as intended, one must use compound quotes:
print_globals `" ${glob0} "'
and not print_globals ${glob0}.
To see this, consider the following example:
local A "a b c d e"
global B "a b c d e"
cap program drop print_prog
program define print_prog
args loc_input
di "print global: $B"
di "print local: `loc_input'"
end
print_prog `A'
print_prog `" `A' "' // prints both A and B as initially intended
The confusion here is given by the fact that B is printed as intended without having to use compound quotes, whereas the same does not apply for the local macro A when it's passed as argument to the program.
In fact, as highligted in the comments below, in the latter case only the first element is passed as program argument (a in the example).
By using compound quotes we supply a b c d e as a single argument and the final result is the one wanted.

How to define map fusion in the Pure language?

I'm experimenting with the Pure language based on term rewriting.
I want to define "map fusion" using an equation, like this:
> map f (map g list) = map (f . succ . g) list;
(The succ is there to verify that the rule kicks in.)
However, it doesn't seem to work:
> map id (map id [2,3,4]);
[2,3,4]
The Pure manual says that
expressions are evaluated using the “leftmost-innermost” reduction strategy
So I suppose what's happening is that the innermost map id [2,3,4] expression is reduced first, so my rule never kicks in.
How to make map fusion work, then?
Here's a related experiment. The first rule doesn't kick in:
> a (b x) = "foo";
> b x = "bar";
> a (b 5);
a "bar"
I should have read the manual more closely. What I needed to do is to turn the pattern into a macro using the def keyword. This way it works:
> def map f (map g list) = map (f . succ . g) list;
> map id (map id [2,3,4]);
[3,4,5]

Resources