Section 1 - Clauses, Types and Rules
Select the Content rulebase on the UniversalAgent browser. Create two new categories from price setting and buying. In the price setting category invent a rule to assert the clause price ?producer ?amount for each producer. Try the antecedent out on the Experiment pane of the instance browser first. Base this rule on a selection of the clauses producer, profitTarget, fixedCost and marginalCost. Check this works by running the simulation and looking under price in the universe's database. Each producer should have one and only one price.
So far all the clauses and rules we have created are forward-chaining. The efficient use of such forward-chaining rules is one of the things that distinguishes SDML from other declarative languages such as Prolog. You could do all your programming using only such clauses and rules, posting intermediate results on the relevant databases. Sometimes, however, you are not interested in these intermediate results, you have essentially the same lines of code in many rules or the computation is quite intensive (as with list-processing). In these cases you might wish to use a special sort of clause which acts rather like an SDML primitive called a backward-chaining clause.
Like SDML primitives these can not be asserted to a database for later reuse but are merely "called" from within the antecedent of a rule to work something out.
Below we are going to define such clauses, one to choose a list of randomly chosen producers and one to choose the producer from such a list who offers the best price.
In the consumer category of the definitions create a clause randomProducerChoice with the following syntax.
To do this you will have to use the add inst type node selection when using the command button to add the second and third nodes. This means that (like primitives) the relevant arguments have to be instantiated before SDML attempts to find bindings for the clause. In this case we will specify the number of producers and a uniquifying term and it will bind with a list of randomly chosen producers of the right length.
Select the Properties tag and select the backward radio-button. An extra tag called Rulebase is added to the right, select this. It is here one writes the rules that will define the effect that the rule will have. In the small empty pane use the command button to add the rule name top-level. For the consequent enter the line randomProducerChoice ?chosenList ?no ?term.
Return to the Experiment pane of the universe then enter and evaluate the following clause:
randomList ?prodList ?prod [1]
producer ?prod
This produces a randomly shuffled list with members determined by bindings of the specified variable by the subclause producer ?prod. Next we want to take a sublist of the right length of this.
Edit the clause to read as below and evaluate:
and
randomList ?prodList ?prod 1
producer ?prod\
subList ?chosenList ?prodList 1 3
Cut and paste this clause to become the antecedent of the top-level rule for the backward-chaining clause randomProducerChoice and edit it to read thus:
and
randomList ?prodList ?prod ?term
producer ?prod\
subList ?chosenList ?prodList 1 ?no
We have now defined our backward clause. Test it by evaluating the clause randomProducerChoice ?prodList 4 1 on the Experiment pane of the universe. Try it with different arguments.
Now define another backward chaining clause bestOf in the same place with the following syntax:
Change it to a backward clause and add a rule called top-level to it with the consequent bestOf ?bestProducer ?minPrice ?listOfProducers ?term. Go back to the Experiment pane. Edit the contents to read:
and
randomProducerChoice ?prodList 4 1\
includes ?prodList ?prod\
price ?prod ?price\
We are using the output from randomProducerChoice to develop and test our new rule. First we find all the prices for the producers in the list. Next we will find the minimum value of all the producers' prices.
Edit the pane to read:
and
randomProducerChoice ?prodList 4 1\
minValue ?minPrice ?price
(and
includes ?prodList ?prod\
price ?prod ?price)\
and evaluate it.
Now we could finish the rule off thus:
and
randomProducerChoice ?prodList 4 1\
minValue ?minPrice ?price
(and
includes ?prodList ?prod\
price ?prod ?price)\
price ?bestProducer ?minPrice
but it is possible that there is more than one producer with the same price. If there is we want our consumer to choose a random producer from all these.
Now edit the clause to read and evaluate:
and
randomProducerChoice ?prodList 4 1\
minValue ?minPrice ?price
(and
includes ?prodList ?prod\
price ?prod ?price)\
randomChoice ?bestProducer ?prod 1
(price ?prod ?minPrice)\
Copy this clause to the antecedent of the backward clause bestOf and edit it to read:
and
minValue ?minPrice ?price
(and
includes ?prodList ?prod\
price ?prod ?price)\
randomChoice ?bestProducer ?prod [?term]
price ?prod ?minPrice
You can now test this clause definition on the experimental pane with the clause:
and
choice ?no\
consumer ?cons\
randomProducerChoice ?prodList ?no ?cons\
bestOf ?bestProd ?minPrice ?prodList ?cons\
then evaluate it.
We have written a clause which lets each consumer randomly try a set number of producers and choose the one with the best price. It uses the backward chaining clauses randomProducerChoice and bestOf to modularise and hide unnecessary intermediate stages.
Create a rule called choose producer in the buying category of the content rulebase with the above antecedent and chosenProducer ?cons ?bestProd ?minPrice for the consequent. Test the model by restarting the simulation and examining the universe's database.
Generated with CERN WebMaker