Discussions related to Visual Prolog
Michel
Posts: 3
Joined: 8 Nov 2025 17:17

SOS... Need help and light

Post by Michel »

Hello, I wrote my first Medical Expert system in 80's... Mix of Turbo Prolog and Turbo C and tistributed by "Faculté des Sciences de Paris".

I need help about my new ES, a new medical one.

1) How can I create a list of lists, aka pathogie :"string name", "symbols remedies" and, then, a list of such a compound facts ?

2) How can I access and show a specific list of those above, progammaticaly, from a clause in response at a selected other list of proposed diseases.

I spend many hours reading and testing samples, some with success, but now I don't obtain other results than "compile errors". Every things is fine but not in the second part of the code...

It is probably very simple, but I do prefer my old "C" programming usage 😉.

Regards, Michel ( ..... from CĂŽte d'Azur, France )

Code: Select all

% Copyright Michel Berr   implement consult inherits formWindow     open core, vpiDomains   facts     sexe : integer := erroneous.     age : integer := erroneous.     patho : integer := erroneous.     /*     *     */     pathoWife : string* :=         [             "GĂ©nĂ©ralitĂ©s...",             "Psychisme...",             "SystĂšme nerveux...",             "Digestion - mĂ©tabolisme...",             "Respiration...",             "Coeur - Vaisseaux - Sang...",             "Reins - Voies urinaires...",             "Rhumatisme - Os - Muscles...",             "GynĂ©cologie...",             "Endocrinologe...",             "Nez - Gorge - Oreilles - Yeux...",             "Peau...",             "Maladies infectieuses..."         ].     pathoMale : string* :=         [             "GĂ©nĂ©ralitĂ©s...",             "Psychisme...",             "SystĂšme nerveux...",             "Digestion - mĂ©tabolisme...",             "Respiration...",             "Coeur - Vaisseaux - Sang...",             "Reins - Voies urinaires...",             "Rhumatisme - Os - Muscles...",             "GĂ©nital Homme...",             "Endocrinologe...",             "Nez - Gorge - Oreilles - Yeux...",             "Peau...",             "Maladies infectieuses..."         ].   clauses     display(Parent) = Form :-         Form = new(Parent),         Form:show().   clauses     new(Parent) :-         formWindow::new(Parent),         generatedInitialize(),         RadioGroup = radioButtonGroup_ctl:getRadioButtonGroup(),         RadioGroup:addSelectionChangedListener(groupListener),         ageChoice_ctl:addList(["Nourrisson", "Enfant", "Adolescent", "Jeune adulte", "Adulte", "Senior"]),         ageChoice_ctl:selectAt(0, false),         consultationCtl:addList(["DĂ©finir le sexe et l'Ăąge."]),         consultationCtl:selectAt(0, true).   predicates     onConsultationCtlMouseDbl : window::mouseDblListener. clauses     onConsultationCtlMouseDbl(_Source, _Point, _ShiftControlAlt, _Button) :-         patho := consultationCtl:tryGetSelectedIndex(),         !,         Symptoms = symptoms::new(This),         Symptoms:show(),         Symptoms:setText("Static text 2"),         symptoms::populateList("my test", age).       onConsultationCtlMouseDbl(_Source, _Point, _ShiftControlAlt, _Button).   predicates     onAgeChoiceSelectionChanged : listControl::selectionChangedListener. clauses     onAgeChoiceSelectionChanged(_Source) :-         consultationCtl:clearAll(),         age := ageChoice_ctl:tryGetSelectedIndex(),         !,         if _F = notErroneous(sexe) then             setPatientProfile(sexe, age)         end if.       onAgeChoiceSelectionChanged(_).   predicates     groupListener : radioButtonGroup::selectionChangedListener. clauses     groupListener(_RadioGroup, SelectedButton) :-         enableGroup_ctl:getCheckedState() = checkButton::checked,         CompareResult = compare(SelectedButton:getText(), "♂"),         !,         if CompareResult = equal then             sexe := 1         else             sexe := 0         end if,         if _F = notErroneous(age) then             setPatientProfile(sexe, age)         end if.       groupListener(_, _).   predicates     setPatientProfile : (integer S, integer A). clauses     setPatientProfile(1, _) :-         consultationCtl:clearAll(),         !,         consultationCtl:addList(pathoMale).     setPatientProfile(0, _) :-         consultationCtl:clearAll(),         !,         consultationCtl:addList(pathoWife).       setPatientProfile(_, _).   % This code is maintained automatically, do not update it manually. facts     consultationCtl : listBox.     radioButtonGroup_ctl : groupBox.     wife_ctl : radioButton.     male_ctl : radioButton.     ageChoice_ctl : listEdit.     enableGroup_ctl : checkButton.   predicates     generatedInitialize : (). clauses     generatedInitialize() :-         setText("consult"),         setRect(vpiDomains::rct(1, 1, 141, 154)),         setDecoration(titlebar([frameDecoration::maximizeButton, frameDecoration::minimizeButton, frameDecoration::closeButton])),         setBorder(frameDecoration::noBorder),         setState([wsf_ClipSiblings, wsf_ClipChildren]),         menuSet(noMenu),         setFont(vpi::fontCreateByName("Verdana", 12)),         consultationCtl := listBox::new(This),         consultationCtl:setText("List Box"),         consultationCtl:setRect(vpiDomains::rct(4, 44, 136, 149)),         consultationCtl:addMouseDblListener(onConsultationCtlMouseDbl),         consultationCtl:setSort(false),         radioButtonGroup_ctl := groupBox::new(This),         radioButtonGroup_ctl:setText("Sexe"),         radioButtonGroup_ctl:setRect(vpiDomains::rct(4, 6, 60, 35)),         radioButtonGroup_ctl:setSize(56, 29),         GroupBox1_ctl = groupBox::new(This),         GroupBox1_ctl:setText("Age"),         GroupBox1_ctl:setRect(vpiDomains::rct(64, 6, 136, 35)),         wife_ctl := radioButton::new(radioButtonGroup_ctl),         wife_ctl:setText("♀"),         wife_ctl:setRect(vpiDomains::rct(5, -1, 27, 12)),         wife_ctl:setFont(vpi::fontCreateByName("Corbel", 20)),         male_ctl := radioButton::new(radioButtonGroup_ctl),         male_ctl:setText("♂"),         male_ctl:setRect(vpiDomains::rct(31, -1, 53, 12)),         male_ctl:setFont(vpi::fontCreateByName("Corbel", 20)),         ageChoice_ctl := listEdit::new(GroupBox1_ctl),         ageChoice_ctl:setRect(vpiDomains::rct(5, 3, 66, 16)),         ageChoice_ctl:setSort(false),         ageChoice_ctl:addSelectionChangedListener(onAgeChoiceSelectionChanged),         ageChoice_ctl:setText("..."),         enableGroup_ctl := checkButton::new(This),         enableGroup_ctl:setRect(vpiDomains::rct(14, 181, 64, 193)),         enableGroup_ctl:setVisible(false),         enableGroup_ctl:setChecked(true),         enableGroup_ctl:setEnabled(true). % end of automatic code   end implement consult

Code: Select all

% Copyright Michel Berr   implement symptoms inherits dialog     open         core,         vpiDomains % % %   facts     remedes : symbol*.   %pathoMain : string.symbol*. %PathoFull : pathoMain*. clauses     display(Parent) = Dialog :-         Dialog = new(Parent),         Dialog:show().   clauses     new(Parent) :-         dialog::new(Parent),         generatedInitialize(),         populateList("dddd", 2).   clauses     populateList(X, Y) :-         stdio::writef("----> %s ----- %d", X, Y),         %listBox_ctl:addList(["My List Box MVB","fffffffff"]),         %symptoms:staticText_ctl:setText("My text"),         stdio::writef("test").   predicates     onOkClick : button::clickResponder. clauses     onOkClick(_Source) = button::defaultAction.   % This code is maintained automatically, do not update it manually. facts     ok_ctl : button.     cancel_ctl : button.     listSymptoms_ctl : listBox.   predicates     generatedInitialize : (). clauses     generatedInitialize() :-         setText("symptoms"),         setRect(vpiDomains::rct(50, 40, 449, 350)),         setModal(true),         setDecoration(titlebar([frameDecoration::closeButton])),         ok_ctl := button::newOk(This),         ok_ctl:setText("&OK"),         ok_ctl:setPosition(172, 284),         ok_ctl:setSize(56, 16),         ok_ctl:defaultHeight := false,         ok_ctl:setAnchors([control::right, control::bottom]),         ok_ctl:setClickResponder(onOkClick),         cancel_ctl := button::newCancel(This),         cancel_ctl:setText("Cancel"),         cancel_ctl:setPosition(236, 284),         cancel_ctl:setSize(56, 16),         cancel_ctl:defaultHeight := false,         cancel_ctl:setAnchors([control::right, control::bottom]),         listSymptoms_ctl := listBox::new(This),         listSymptoms_ctl:setText("List Box"),         listSymptoms_ctl:setRect(vpiDomains::rct(36, 38, 370, 270)),         StaticText_ctl = textControl::new(This),         StaticText_ctl:setText("Static text"),         StaticText_ctl:setRect(vpiDomains::rct(46, 6, 260, 28)). % end of automatic code   end implement symptoms
User avatar
Thomas Linder Puls
VIP Member
Posts: 1483
Joined: 28 Feb 2000 0:01

Re: SOS... Need help and light

Post by Thomas Linder Puls »

Hi Michel.

If I understand the problem correctly, the it sounds like you should use a map on the outer level and a list or set at inner level. (I will use English terms instead of French).

A map is a "table" which maps keys into values. You want to map a certain pathology into some remedies.

Given a certain pathology you want to look it up in the map to find the associated remedies.

Here are some domain definitions:

Code: Select all

domains     remedies = string*.     remedyTable = mapM{string Pathology, remedies Remedies}.
The first line defines "remedies" as a list of strings, i.e. a list of remedies. The second line defines "remedyTable" as a map from string (Pathology) to remedies (Remedies).

The "M" in mapM means that the map is modifiable, so we can update it with our data.

Let us have a remedyTable in a fact variable:

Code: Select all

facts    remedyTable : remedyTable := mapM_redBlack::new().
I have initialized it to a new (empty) mapM_redBlack object.

Now we can insert entries in the table (I suggest using a less hard coded to insert the data, but for now we will just hardcode it).

Code: Select all

predicates     initializeRemedyTable : (). clauses     initializeRemedyTable() :-         remedyTable:set("heart", ["digogxin", "carvedilol", ...]),         ...
The predicate above inserts a list of remedies for "heart" conditions. I don't know if this is what you have in mind, but I guess you can adjust it to your data.

Given a pathology we can try to obtain an associated list of remedies like this:

Code: Select all

predicates     tryGetRemedies : (string Pathology) -> remedies Remedies determ. clauses     tryGetRemedies(Pathology) = remedyTable:tryGet(Pathology).
I hope this gives you a starting point for solving your problem.

You can read more details about "collections" here: Collection library.
Regards Thomas Linder Puls
PDC
Michel
Posts: 3
Joined: 8 Nov 2025 17:17

Re: SOS... Need help and light

Post by Michel »

Thanks...

"BRAVO"!!!! It is exactly what I have in mind. I worked some years ago with Nasa CLIPS, revisited to work with UNIX ( the defunct Unixware :-( ) and the Motif library to test an expert system, on line, running on a server using Tarentella... Worked fine but, now, it is mandatory to use MS Window.

I leave sadly "C" to work with VIP : a very, very fine tool and compiler but hard to fully understand for a beginner with OOP like me.

Best regards, Michel
User avatar
drspro2
VIP Member
Posts: 115
Joined: 28 Apr 2006 12:03

Re: SOS... Need help and light

Post by drspro2 »

dear Michel,

i would be glad to help in any form. I am not by far as an expert as Thomas but I use prolog everyday to develop programs, currently I program prolog for a French company and we gather periodically online with for google meet or teams.

I might be able to help you getting started with the vp prolog in an online session.

Also if Thomas's code example of the RedBlack tree is already sufficient for you to get started that is perfectly fine.
Michel
Posts: 3
Joined: 8 Nov 2025 17:17

Re: SOS... Need help and light

Post by Michel »

First, to drspro2.... thanks for such a proposition. I do "max" to work alone "comme un grand", but I ask you with pleasure if I need somme help.

Second, to Thomas : it works, the code is fine !!! It was exactly what I dream about.

Warm regards.

Michel