CLIPS simple percentage defrule - expert-system

At the end, when the program is supposed to print the percentage certainties, the program hangs. What might be wrong? It has to be the calculate-percentage rule, since when removed, the non-percentaged data is printed.
(defmodule PRINT-RESULTS (import MAIN ?ALL))
(defrule PRINT-RESULTS::calculate-percentages
?var <- (religion (name ?religion) (aspects $?aspects) (certainty ?certainty))
=>
(modify ?var (certainty =(*(/ ?certainty 700)100))))
(defrule PRINT-RESULTS::print-religion
?rel <- (religion (name ?religion) (aspects $?aspects) (certainty ?certainty))
=>
(retract ?rel)
(printout t crlf RELIGION: " "
?religion crlf ASPECTS: " "
?aspects crlf CERTAINTY: " "
?certainty crlf))

It appears that you are being caught in an infinite loop. When you modify a deftemplate instance, you are replacing the original with the modified instance, which in your situation will match calculate-percentages again and again. So you need to prevent this infinite loop of rule matches.
Since you are using modules, consider calculating your certainty in a module other than PRINT-RESULTS (I'll refer to the other module as UPDATE-CERTAINTY). Then in the then part of your calculate-percentages rule, you can pop the UPDATE-CERTAINTY module to prevent the rule from matching the modified fact.

Alternately, you can use an additional slot in your facts to indicate whether the computation has been done on the fact (in this example the status slot):
(defrule PRINT-RESULTS::calculate-percentages
?var <- (religion (name ?religion) (status ~final) (aspects $?aspects) (certainty ?certainty))
=>
(modify ?var (status final) (certainty =(*(/ ?certainty 700)100))))

Related

CASE WHEN textfield does not equal a value

In a Netsuite saved search I am trying to create a formula that - in part - gives a field value if a textfield does not equal a word - in this case the word is "consol". I tried the below but got an error and am lost on how I can accomplish this.
CASE WHEN {custbody_eym_exhibitor_name} = 'Consol' THEN {custrecord511.custrecord501} WHEN {custrecord169.custrecord173} IS NOT NULL AND {custbody_eym_exhibitor_name} IS NOT 'Consol' THEN {custrecord169.custrecord173} ELSE {custbody90} END
Any help is appreciated.
I know Suite Answer Id 10101 suggest you'd be able to do CASE WHEN -- THEN -- WHEN -- THEN -- ELSE -- END. However, this has never worked for me in a saved search. I've always have to do CASE WHEN -- THEN -- ELSE (CASE WHEN -- THEN -- ELSE -- END) END.
If you are trying to do the following:
If custbody_eym_exhibitor_name is Consol then return custrecord511.custrecord501, and stop evaluating.
If custbody_eym_exhibitor_name is not Consol then check if custrecord169.custrecord173 is NULL, and continue evaluating.
If custrecord169.custrecord173 is NULL then return custbody90, and stop evaluating. If custrecord169.custrecord173 is not NULL then return custrecord169.custrecord173, and stop evaluating.
This should work:
CASE WHEN {custbody_eym_exhibitor_name}='Consol' THEN {custrecord511.custrecord501} ELSE NVL({custrecord169.custrecord173},{custbody90}) END
If you wanted to check if custbody_eym_exhibitor_name contains Consol change {custbody_eym_exhibitor_name}='Consol' to {custbody_eym_exhibitor_name} LIKE '%Consol%' .
Also both tests for 'Consol' will be case sensitive. To work around this you can change {custbody_eym_exhibitor_name}='Consol' to LOWER({custbody_eym_exhibitor_name})='consol'

Excel formula to find two words after the prefix

I'm exporting a Jira issue into Excel to pull data from the description.
An example of the format would be:
"Author: Bob Bryant This is a test JIRA"
So that entire string occupies a single cell in Excel
I need to do an =IF(ISNUMBER(SEARCH("*Author*",Description)),"Author:","")
But instead of '"Author:"' I need it to take the 2 words after that (users full name), in this case I need it to take "Bob Bryant"
Unfortunately, Excel is not able to use regular expression (which would be much easier). You can workaround it with a temporary text substitution using SUBSTITUTE function.
With:
Prefix - the cell with the prefix, e.g. "Author:"
Description - the cell with original/source text
This is the formula you need is:
=IF(ISERR(SEARCH(Prefix;Description));"(no "&Prefix&" found)";IFERROR(TRIM(MID(Description;LEN(Prefix)+1;SEARCH("$$$";SUBSTITUTE(Description&" ";" ";"$$$";3))-LEN(Prefix)));"(too short)"))
Let's explain deeper:
=IF(
ISERR(SEARCH(Prefix;Description)); -- consider only cells with the right prefix (Author:)
"(no "&Prefix&" found)"; -- Prefix not found: return message
IFERROR( -- Prefix found: proceed
TRIM( -- remove any leading/trailing spaces
MID( -- return the text between prefix and 3rd space
Description;
LEN(Prefix)+1; -- start after the prefix
SEARCH( -- end before the substituted text ($$$)
"$$$";
SUBSTITUTE( -- substitute 3rd space (most important!)
Description&" "; -- add extra space (in case there's no other text after the name)
" ";
"$$$";
3))-LEN(Prefix)));"(too short)"))
Note, you might need to replace ; with , in your formula (depending on your system locales/regional settings).

Vim: Adding automatic alphabetic and/or numeric index to current file name?

I want to implement a loose version of Niklas Luhmann's
Zettelkasten
in Vim. At the core of his method are note snippets that Continue the current
note or Brahch off from it, introducing a slightly different topic or
concept. In the note name, letters indicate branches and numerals
indicate continuations. Like so:
note100
note101
note101a # branches off from note100 (related topic)
note101b # also branches off from note100 (related topic)
note101b01 # continues note101b (same topic)
note101b02 # also continues note101b (same topic)
note101c
note102
To implement this in Vim, I need new file
names that are automatically enumerated either as a "continuation" or
a "branch" of the note in current buffer. As a non-coder making first "real" steps in Vimscript, this is where I'm at with the Branching Note function:
function! ZettelkastenNewBranchingNote()
let b:current_note_name = expand('%:t:r')
let b:new_branching_note = call(BranchingFunctionThatReturnsNewNoteName)
silent execute 'edit' b:new_branching_note
echomsg 'New branching note ' b:new_branching_note 'created.'
endfunction
The BranchingFunctionThatReturnsNewNoteName() should take
b:current_note_name and extend it with automatic alphabetical(!)
index (counting alphabetically upwards). How could I accomplish this?
Also, for my New Continued Note function: how could I numerically
count upwards from the last numeric part of the current file name? (E.g. 100a01 > 100a02.)
Thanks for any advice!
(Somewhat relatedly, here
the Nexus plugin is suggested, but I'd prefer to keep my script
self-contained.)
You provide a great deal of context (which is great), but are light on the needed algorithm. To me, it looks like this: If the current file ends with a letter, increase it, else (it's a number), append an a to start the alphabetical sequence.
Checks are done in Vim with regular expressions; \a is a short form for [A-Za-z] (you could also write [[:alpha:]]; yes it's that flexible), and $ anchors it to the end of the name:
if b:current_note_name =~ '\a$'
...
Extract the last character with matchstr().
let lastAlpha = matchstr(b:current_note_name, '\a$')
if lastAlpha ==? 'z'
" TODO: Handle overflow
endif
To "increase" an alphabetical character, convert it first to a number, increase, then back:
let newAlpha = nr2char(char2nr(lastAlpha) + 1)
To replace, you use substitute(), again with the same regexp.
let b:new_branching_note = substitute(b:current_note_name, '\a$', newAlpha, '')
Appending is simple:
else
let b:new_branching_note = b:current_note_name . 'a'
endif

Monitoring Process of Cases[] on a Very Large Body of Information

I'm currently undertaking operations on a very large body of text (~290MB of plain text in one file). After importing it into Mathematica 8, I'm currently beginning operations to break it down into lowercase words, etc. so I can begin textual analysis.
The problem is that these processes take a long time. Would there be a way to monitor these operations through Mathematica? For operations with a variable, I've used ProgressIndicator etc. But this is different. My searching of documentation and StackOverflow has not turned up anything similar.
In the following, I would like to monitor the process of the Cases[ ] command:
input=Import["/users/USER/alltext.txt"];
wordList=Cases[StringSplit[ToLowerCase[input],Except[WordCharacter]],Except[""]];
Something like StringCases[ToLowerCase[input], WordCharacter..] seems to be a little faster. And I would probably use DeleteCases[expr, ""] instead of Cases[expr, Except[""]].
It is possible to view the progress of the StringSplit and Cases operations by injecting "counter" operations into the patterns being matched. The following code temporarily shows two progress bars: the first showing the number of characters processed by StringSplit and the second showing the number of words processed by Cases:
input = ExampleData[{"Text", "PrideAndPrejudice"}];
wordList =
Module[{charCount = 0, wordCount = 0, allWords}
, PrintTemporary[
Row[
{ "Characters: "
, ProgressIndicator[Dynamic[charCount], {0, StringLength#input}]
}]]
; allWords = StringSplit[
ToLowerCase[input]
, (_ /; (++charCount; False)) | Except[WordCharacter]
]
; PrintTemporary[
Row[
{ "Words: "
, ProgressIndicator[Dynamic[wordCount], {0, Length#allWords}]
}]]
; Cases[allWords, (_ /; (++wordCount; False)) | Except[""]]
]
The key to the technique is that the patterns used in both cases match against the wildcard _. However, that wildcard is guarded by a condition that always fails -- but not until it has incremented a counter as a side effect. The "real" match condition is then processed as an alternative.
It depends a little on what your text looks like, but you could try splitting the text into chunks and iterate over those. You could then monitor the iterator using Monitor to see the progress. For example, if your text consists of lines of text terminated by a newline you could do something like this
Module[{list, t = 0},
list = ReadList["/users/USER/alltext.txt", "String"];
Monitor[wordlist =
Flatten#Table[
StringCases[ToLowerCase[list[[t]]], WordCharacter ..],
{t, Length[list]}],
Labeled[ProgressIndicator[t/Length[list]], N#t/Length[list], Right]];
Print["Ready"]]
On a file of about 3 MB this took only marginally more time than Joshua's suggestion.
I don't know how Cases works, but List processing can be time consuming, especially if it is building the List as it goes. Since there is an unknown number of terms present in the processed expression, it is likely that is what is occurring with Cases. So, I'd try something slightly different: replacing "" with Sequence[]. For instance, this List
{"5", "6", "7", Sequence[]}
becomes
{"5", "6", "7"}.
So, try
bigList /. "" -> Sequence[]
it should operate faster as it is not building up a large List from nothing.

text with redundant side chars formatting in emacs

I did lots of search without luck. I think even this is easy but it could help, so here it goes.
Here the goal is to format a kind of Java String to plain text.
For example, consider a String in java code,
logger.LogText( "Hi, this is 1st line " + "\n" +
"speak sth. in 2nd line " + "\n" +
"answered...? ");
and i want to copy from the whole String and paste to my plain text file, then run
M-x some-format-function-by-template-on-selection
and i got a result
Hi, this is 1st line
speak sth. in 2nd line
answered...?
Is there a built-in command for this?
It's not have to use template, but don't you think it's cool?
Currently i try to use 'align' to work around.
The built-in commands are the regexp functions :-)
(defun my-reduce-to-string (start end)
"Extract a quoted string from the selected region."
(interactive "r")
(let* ((text1 (replace-regexp-in-string ".*?\"\\([^\"]+\\)\"[^\"]*" "\\1"
(buffer-substring start end)))
(text (replace-regexp-in-string "\\\\n" "\n" text1)))
(delete-region start end)
(insert text)))
Note that this is a destructive function -- it replaces the text in the buffer as requested.

Resources