I want to build a semi-natural language interface for a data warehouse. A simple data model looks for example like this:
Company
- attribute 'name'
- reference to 'Departments'
Department
- attribute 'type'
- reference to 'Employees'
Employee
- attribute 'age'
- attribute 'salary'
And I would like to make queries like so:
ACME employees, Bugs Bunny salary, ACME department types etc.
For input that is not in the grammar, I would call the database and resolve say ACME into Company.
... and turn the queries into paths that my database language will understand:
[Company].departments.employees, [Employee].salary, [Company].departments.type.
I remember using SWI-Prolog way back when to parse English sentences and say if they are correct. Is Prolog still the way to go in this case?
Thanks
Even, better, I now use DCG with embedded Prolog rules.
So, for a model that has classes and attributes like this:
c(company, class(company)) --> [company].
a(company, attribute(name)) --> [name].
I can ask for attributes of a class of a class:
q(q(A,C1,C2)) --> a(T1,A), [of], c(T1,C1)
,[of], c(T2,C2), {is_child(T1, T2)}.
And get a tree back as an answer.
In SWI-Prolog, there is Chat80 ready to install. I think could be very similar to what you are after, mutatis mutandis.
Just a sample query from the session log (note: was my own old port of chat80 to SWI-Prolog, the pack is presumably more functional, but I haven't tried to run):
what rivers are there ?
Parse: 0.0168457sec.
whq
$VAR
1
s
np
3+plu
np_head
int_det(B)
[]
river
[]
verb(be,active,pres+fin,[],pos)
void
[]
Semantics: 0.0170898sec.
answer([B]) :-
river(B)
& exists B
true
Planning: 0.0sec.
answer([B]) :-
river(B)
& exists B
true
amazon, amu_darya, amur, brahmaputra, colorado, congo_river, cubango, danube, don, elbe, euphrates, ganges, hwang_ho, indus, irrawaddy, lena, limpopo, mackenzie, mekong, mississippi, murray, niger_river, nile, ob, oder, orange, orinoco, parana, rhine, rhone, rio_grande, salween, senegal_river, tagus, vistula, volga, volta, yangtze, yenisei, yukon and zambesi.
Reply: 0.166992sec.
The logical form required by discourse to answer a query it's the central point of the system. Not really easy to craft from ground!
I read the book Prolog and Natural Language Analysis, F.Pereira, S.Shieber, 1987
(translated in Italian), still my preferred! The english original it's freely available here.
Have ended up with this example that translates a 'sentence' into a path in the model:
% root classes
class(ceo).
% model relations
attribute_of(age, ceo).
attribute_of(salary, ceo).
% grammar of relations
attribute('age', age).
attribute('salary', salary).
attribute('money', salary).
% answer format
answer([Class, Attribute], Class, Attribute).
% language rules
% query(Attribute,'of',Object, Answer).
query(AttributeQ, 'of', ClassQ, Answer) :-
db(ClassQ, Class), attribute(AttributeQ, Attribute), attribute_of(Attribute, Class), answer(Answer, Class, Attribute).
% database
db('Bugs Bunny', ceo).
As an example, the following query:
?- query('age','of','Bugs Bunny', Answer).
...gives me:
Answer = [ceo, age].
Related
Recently, I started to study owlready, and faced with much problem.
I defined a PropertyChain as follows.
class friend(Person >> Person, SymmetricProperty):
pass
class potentialFriend(Person >> Person):
# potentialFriend := friend o friend
equivalent_to = PropertyChain([friend, friend])
I tried to get person.potentialFriend.indirect(), but failed. I read the source codes, since the doc on web is too simple, and found that PropertyChain works like a list, I thought it returned a Property. How do I compliment what I want?
How do you use PropertyChain? Is there some concrete examples.
PS: The source codes(.py files) indent with only two whitespaces, :o!
You can use:
P.property_chain.append(PropertyChain([P1, P2]))
...where P1 and P2 are already created ObjectProperties. In your case, P is potentialFriend. P1 and P2 are both friend.
For the reasoner to infer the property chain, don't forget to set its parameter infer_property_values to True :
sync_reasoner(infer_property_values = True)
After that, the reasoner manages to infer the property and you can get it with person.potentialFriend.indirect().
I have this in my controller
public function editProfile(Request $request){
$question1 = Question::where('group',1)->lists('question', 'id');
$question2 = Question::where('group',2)->lists('question', 'id');
return view('user', compact(''question1', 'question2'));
}
$question = {\"1\":\"What is the first name of your best friend in high school?\",\"2\":\"What was the name of your first pet?\",\"3\":\"What was the first thing you learned to cook?\",\"4\":\"What was the first film you saw in the theater?\"}
$question2 = {\"5\":\"Where did you go the first time you flew on a plane?\",\"6\":\"What is the last name of your favorite elementary school teacher?\",\"7\":\"In What city or town does your nearest sibling live?\"}
I would like to translate the value in both question 1 and question 2 and pass it to user blade without changing the key, Any suggestions?
As specified at the localization doc, you need to populate a lang file with translation strings. So, let's say you want to show both Spanish and English strings. In this case you'd need to create two files: /resources/lang/en/messages.php and /resources/lang/es/messages.php. The content of one of those files would be somewhat like this:
<?php
// resources/lang/es/messages.php
return [
'welcome' => 'Bienvenido'
];
This way, you could access the strings in there with the following method: __('messages.welcome'), which would return the string for the language set on your config/app.php -- the default entry is en, by the way, but you can set it to whatever you want. The value in there will define which language will be chosen when selecting strings.
Another method to create translation strings is using the string itself as key, storing them in a JSON file instead of PHP. For example, the following translation string:
{
"I love programming.": "Me encanta programar."
}
would be accessible through this: __('I love programming.').
Having said that, you may solve your problem through the two methods presented above. You could store in your DB keywords for the questions instead of the whole text, and create translation for as many languages as you want. Also, you could keep the questions in your database and create translation strings for those questions. Finally, you'd need to iterate over the fetched entries and translate each one of them, or use some Collection helper to do the hard work for you, like transform or map.
I have 3 fields(Name, Code, displayNmae) in the list, here I need to get a list as output in which I get all the fields but need to split displayname field by colon and then add list again for each splitted value which is display name.
Hence in output list I will have the 5 row as total display name are 5 in 2 rows.
Need the linq query for this problem.
Name Code displayName
Napkins_tableware - Napkins and tableware - 3_ply:conventional_napkins
hand-towel - Hand and Towel - 2_ply:towel roll:coloured
Output should be like this :
Name Code displayName
Napkins_tableware - Napkins and tableware - 3_ply
Napkins_tableware - Napkins and tableware - conventional_napkin
hand-towel - Hand and Towel - 2_ply
hand-towel - Hand and Towel - towel roll
hand-towel - Hand and Towel - coloured
Solution which I tried in C#
foreach(ProductDetailsWithFilters qs in CategoryProductList())
{
foreach(string friendlyname in qs.displayName.Split(':'))
{
qs.displayName = friendlyname;
tempCategoryProductList.Add(qs);
}
}
If you're translating to LINQ, when you have nested foreach loops those correspond to 'from' clauses in query syntax (or in dot syntax, subsequent ones become SelectMany, see below.) The following should be close to what you want:
var query =
from qs in CategoryProductList()
from friendlyName in qs.displayName.Split(':')
select new ProductDetailsWithFilters(qs.Code, qs.Category, friendlyName);
Note: Because functional programming should be side-effect-free, it's better to select a new instance ProductDetailsWithFilters than it is to modify the existing one in your query. My presumption is that you can call a constructor to build a new one of these.
For you to modify the existing property like your loop implementation does, you would have to iterate over the result -- LINQ doesn't provide such a thing in the framework. Such side-effects often lead to hard-to-find bugs.
To do the equivalent of the above query with a SelectMany and dot-syntax:
var query = CategoryProductList()
.SelectMany(
qs => qs.DisplayName.Split(':'),
(qs, friendlyName) => new ProductDetailsWithFilters(qs.Code, qs.Category, friendlyName));
Both lead to functionally identical code. In this case, I tend to prefer the query-syntax over the dot-syntax partly because because there are several SelectMany overloads and handling the projection involves repeating the variables across both lambda expressions. If you had another "from" to add, the query-syntax hides the management of 'transparent identifiers' that you would otherwise have to deal with in dot-syntax equivalent code. Whatever your preference, you now have both.
It's worth noting that queries are lazy -- they do nothing until you iterate over their result. So it's really what you do with the result from here that is the interesting part - store it .ToList(), directly data-bind it to a UI, use it to service a web-API, etc...
How can I do the following:
data: ls_header type BAPIMEPOHEADER.
" fill it
write ls_header.
currently I'm getting an error because write can not parse the complex type to a string. Is there a simple way to get this code running in abap?
You could use something like:
DATA: g_struct TYPE bapimepoheader.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE g_struct TO FIELD-SYMBOL(<f>).
IF sy-subrc NE 0.
EXIT.
ENDIF.
WRITE: / <f>.
ENDDO.
Perhaps not exactly the answer you expect: If you list each field.
This can be done quite easy via the Pattern-mask in SE38:
Select the Write-pattern:
Enter the structure you want:
Select the fields
Confirm with "Copy"
Confirm and you get
WRITE: bapimepoheader-po_number,
bapimepoheader-comp_code,
bapimepoheader-doc_type,
bapimepoheader-delete_ind,
bapimepoheader-status,
bapimepoheader-creat_date,
bapimepoheader-created_by,
bapimepoheader-item_intvl,
bapimepoheader-vendor,
bapimepoheader-langu,
bapimepoheader-langu_iso,
bapimepoheader-pmnttrms,
bapimepoheader-dscnt1_to,
bapimepoheader-dscnt2_to,
bapimepoheader-dscnt3_to,
bapimepoheader-dsct_pct1,
bapimepoheader-dsct_pct2,
bapimepoheader-purch_org,
bapimepoheader-pur_group,
bapimepoheader-currency,
bapimepoheader-currency_iso,
bapimepoheader-exch_rate,
bapimepoheader-ex_rate_fx,
bapimepoheader-doc_date,
bapimepoheader-vper_start,
bapimepoheader-vper_end,
bapimepoheader-warranty,
bapimepoheader-quotation,
bapimepoheader-quot_date,
bapimepoheader-ref_1,
bapimepoheader-sales_pers,
bapimepoheader-telephone,
bapimepoheader-suppl_vend,
bapimepoheader-customer,
bapimepoheader-agreement,
bapimepoheader-gr_message,
bapimepoheader-suppl_plnt,
bapimepoheader-incoterms1,
bapimepoheader-incoterms2,
bapimepoheader-collect_no,
bapimepoheader-diff_inv,
bapimepoheader-our_ref,
bapimepoheader-logsystem,
bapimepoheader-subitemint,
bapimepoheader-po_rel_ind,
bapimepoheader-rel_status,
bapimepoheader-vat_cntry,
bapimepoheader-vat_cntry_iso,
bapimepoheader-reason_cancel,
bapimepoheader-reason_code,
bapimepoheader-retention_type,
bapimepoheader-retention_percentage,
bapimepoheader-downpay_type,
bapimepoheader-downpay_amount,
bapimepoheader-downpay_percent,
bapimepoheader-downpay_duedate,
bapimepoheader-memory,
bapimepoheader-memorytype,
bapimepoheader-shiptype,
bapimepoheader-handoverloc,
bapimepoheader-shipcond,
bapimepoheader-incotermsv,
bapimepoheader-incoterms2l,
bapimepoheader-incoterms3l.
Now you can make a simple replacement of bapimepoheader with ls_header and you have an output of all fields of the structure.
Maybe this is not elegant and you must adapt your report, if the structure changes. But I like this way, because often I don't need all fields and I can select the fields in an easy way.
I know two ways, one is procedural, the other is oop.
Here is the procedural approach.
Select the structure's fields (or whatever else You might need ) from the data-dictionary table DD03L into a local internal table.
Loop over the table into a work-area
Check, whether current field is a flat single datatype, and if so,
Assign component workarea-fieldname of structure ls_header into anyfieldsymbol
Write anyfieldsymbol
Do You need the code ?
Class CL_ABAP_CONTAINER_UTILITIES was specially introduced for that by SAP.
Use FILL_CONTAINER_C method for output the structure in a WRITE manner:
DATA: ls_header type BAPIMEPOHEADER.
CALL METHOD CL_ABAP_CONTAINER_UTILITIES=>FILL_CONTAINER_C
EXPORTING
IM_VALUE = ls_header
IMPORTING
EX_CONTAINER = DATA(container)
EXCEPTIONS
ILLEGAL_PARAMETER_TYPE = 1
others = 2.
WRITE container.
You can write your structure to a string and then output the string. Same method idoc segments are created.
HijrahDate hd=HijrahChronology.INSTANCE.date(LocalDate.of(2014,11, 25));
If we have HijrahDate Instance , it is expected to have a method in UmalquraCalendar API that shows the name of month :
i inspect properties of this instance using groovy API :
['era':AH,
'class':class java.time.chrono.HijrahDate,
'prolepticMonth':17233,
'eraValue':1,
'dayOfWeek':2,
'leapYear':false,
'chronology':Hijrah-umalqura,
'dayOfYear':32]
However we don't find the month name which must be one of the following list items :
Muḥarram (محرم meaning "forbidden"), so called because battle was
forbidden (haram) during this month. Muharram includes the Day of
Ashura.
Ṣafar (صفر meaning "void"), supposedly named thus because
pagan Arab houses were empty this time of year while their occupants
gathered food.
Rabīʿ I (Rabīʿ al-Awwal, ربيع الأوّل) meaning "the
first spring".
Rabīʿ II (Rabīʿ ath-Thānī ربيع الثاني or Rabīʿ al-Ākhir
ربيع الآخ
.....................
............ so on SEE
Thus , since there is no attribute save month's name , it is expwcted to have a method retrieve this info ?
What's this method?
The date does not contain information about the names of the months or days. To get that you need a formatter:
System.out.println(DateTimeFormatter.ofPattern("MMMM").format(hd));
prints Safar.
Since the main language of UmalQura is the arabic langugage, Developers & programmers who uses UmalQuraCalender want to display the month in arabic. Thus , we base on #assylias answer we can add the Locale object to print صفر instead of Safar
System.out.println(DateTimeFormatter.ofPattern("MMMM").format(hd,new Locale("ar")));
public String getIslamicDate(){
return DateTimeFormatter.ofPattern("MMMM",new Locale("ar")).format(HijrahDate.now());
}
I think this should work just fine and return the month in arabic language