[Next] [Previous] [Up] [Top] [Contents]

Section 2 - Modules, Time Levels and Lists

2.13 Some longer rules


We are now in a position to write some of the more interesting rules. First those to implement the customer' purchasing decisions we will start with a similar rule to that used yesterday for the first consumer in the queue.

Create a rule called buying - first in the buying category of the Content rulebase with antecedent:

and

time iteration 1\

choice ?no\

currentConsumer ?cons\

randomProducerChoice ?prodList ?no ?cons\

bestOf ?bestProd ?minPrice ?prodList ?cons\

requires ?cons ?req\

getsMoney ?cons ?money\

is ?volBought (min ?req (truncated ?money / ?minPrice))

and consequent:

bought ?cons ?volBought ?bestProd ?minPrice

This uses the backwards chaining clauses randomProducerChoice and bestOf we defined yesterday. The first line checks that this rule will only fire in the first iteration of each week, i.e. for the first in the complete queue. It then produces a random list of producers of the set length, finds the producer with the best price and then buys as much as it can afford. Now in the rule for subsequent consumers we can allow them to copy the last consumer if that is of benefit to them.

Create a rule called buying - subsequent in the buying category of the Content rulebase with antecedent:

and

choice ?no\

currentConsumer ?cons\

randomProducerChoice ?randList ?no ?cons\

last iteration (currentConsumer ?lastCons)\

last iteration (bought ?lastCons ?lastVolBought ?lastBestProd)\

appended ?prodList ?randList [?lastBestProd]\

bestOf ?bestProd ?minPrice ?prodList ?cons\

requires ?cons ?req\

getsMoney ?cons ?money\

is ?volBought (min ?req (truncated ?money / ?minPrice))

and consequent:

bought ?cons ?volBought ?bestProd ?minPrice

This is the same as the last rule except that it retrieves the producer chosen by the consumer in the last iteration with the clause section

last iteration (currentConsumer ?lastCons)\

bought ?lastCons ?lastVolBought ?lastBestProd\

and then adds this producer to the list of randomly sampled producers with the line

appended ?prodList ?randList [?lastBestProd]\

The rule can not fire in the first iteration because the clause

last iteration (currentConsumer ?lastCons)\

will fail as there was not a last iteration then.

Now restart the simulation and examine the database of the model instance at various stages to see what is happening (look especially at the clauses starting with bought).

At the moment no producers survive more than one period, because we have not written a rule to do this. Our intention is that producers survive if they have any capital left, therefore we need to do some accounting.

Go to the Final iteration rulebase and create an accounting category. First we need a rule to count up the sales, so create a rule called sales with antecedent:

and

producer ?producer\

time iteration ?now\

total ?totalSales ?volume

(and

inInterval ?iterationNo 1 ?now\

when iteration ?iterationNo (bought ?consumer ?volume ?producer ?price))

and consequent:

sold ?producer ?totalSales

The total primitive adds up all the values of ?volume that result from bindings of the sub-clause

and

inInterval ?iterationNo 1 ?now\

when iteration ?iterationNo (bought ?consumer ?volume ?producer ?price)

which in turn evaluates the clause bought ?consumer ?volume ?producer ?price at each iteration from 1 to the current (and final) iteration number, 10. For obvious reasons you can only use the when predicate to look backwards in time from the time it is evaluated. It would have been more efficient (in this case) to have asserted the bought clauses as all week (bought ...) and then we would not need the when iteration bit inside the total clause. Fetching from time stages more than two back can be slightly slower in SDML because of it may have stored these in virtual memory (i.e. on disk).

Now add a rule called profit in the same place with antecedent:

and

producer ?producer\

fixedCost ?producer ?fc\

marginalCost ?producer ?mc\

sold ?producer ?volSold\

price ?producer ?price\

is ?profit ?volSold * ?price - ?fc - ?mc * ?volSold

and consequent:

profit ?producer ?profit

This just does some simple arithmetic. We are now in a position to write the rules to calculate the new capital and assert their survival if they are solvent.

In the Initial iteration rulebase add a rule called surviving producers under the producers category with antecedent:

and

last week (and

capital ?prod ?oldCap\

profit ?prod ?profit)\

is ?newCap ?oldCap + ?profit\

notInferred

less ?newCap 0

and consequent:

all week (and

producer ?prod\

capital ?prod ?newCap)

Note the use of last week to retrieve information from the end of last week and the combination of and and all week to assert two clauses for the whole week. Finally we must write rules to get the producers to set their prices each week. This will be done by three rules lower price, keep price, and raise price.

In the content rulebase create a category called under the prices category create a rule called keep price with antecedent:

and

oldProducer ?producer\

last week (price ?producer ?price)\

last week (profit ?producer ?lastProfit)\

greater ?lastProfit 0

and consequent:

all week (price ?producer ?price)

This rule says that an existing producer will keep its price the same as last week if it made a profit. The next rule will be raise price with antecedent:

and

oldProducer ?producer\

last week (price ?producer ?lastPrice)\

last week (profit ?producer ?lastProfit)\

notInferred

greater ?lastProfit 0\

marginalCost ?producer ?mc\

less ?lastPrice ?mc\

raiseProportion ?factor\

is ?newPrice ?lastPrice * ?factor

and the consequent:

all week (price ?producer ?newPrice)

The start of the consequent is similar to the last rule but this time we check for not making a profit (notInferred greater ?lastProfit 0). The simple rule I decided on was to raise the price if the price was less than the marginal cost.

Write a rule lower price similar to the last but so that it will lower the price if the price is above the marginal cost (use the factor set by lowerProportion). To save time you can start by using the copy rule command from this pane. Then restart the simulation to see what occurs.

To see the results in a more graphical way go to the Line Chart page of the model instance. Select the select current stage command using the command button in the Selected stage: pane and enter the following clause in the middle pane and evaluate it:

and

time week ?now\

inInterval ?x 1 ?now\

when week ?x

(price ?z ?y)

It is likely that all the prices are going steadily downwards. Make a similar graph of the profits and then the amounts sold. This time you have to use evaluate final - why do you think this is? To get a key to your graphs use the command button in the graph pane.

Similarly you might want a scatter diagram of profits vs. initial profit targets. Select the Scatter Chart and evaluate the clause (using evaluate final):

and

profitTarget ?z ?x\

profit ?z ?y


An introduction to SDML - Bruce Edmonds - 13 JUL 99
[Next] [Previous] [Up] [Top] [Contents]

Generated with CERN WebMaker