Let's talk about that Light ...

Copyright © by Henk Meeter

A little reflection ...

It had occurred to me, after writing my last two articles about some of the possibilities now available for making use of Advanced Mode in ERP2005 and later releases, that perhaps I should turn the two articles into a series.

And interestingly enough, almost immediately after "getting" the thought, I "got" an email from a consultant I've known for years.

He's been in the business of Product Configuration since 1996, which means almost from the very beginning of its "real" appearance within the SAP world, and anybody who knows him as well as I do would agree that he's brilliant. One of the best, probably that you'll ever find.

But like most Product Configuration consultants within the SAP world, he's got little experience with Advanced Mode. Hence his questions, which I will cite here, and attempt to answer, as the third installment in this "Getting Acquainted with Advanced Mode" series.

You'll recall that in our last installment we talked about a Pneumatic Valve Terminal, including anywhere from eight to sixty-four individually configurable Valve positions, where there are pronounced dependencies between the configurations of adjacent Valves.

And you'll recall, too, that we introduced the peculiar to Advanced Mode device of the Abstract Data Type, or ADT (for short), which is nothing more than a Characteristic specially defined as a pointer to an Instance, if Single-valued, or Instances, if Multi-valued of a particular Class.

In our case we've defined the following in our master data setup:

Class: (300) Valve_Terminal

Class: (300) Valve

Characteristic: Position_number, Numeric, RSV, Values={1-999}

Characteristic: Valve_On_Left, ADT, Class={(300) Valve}

Characteristic: Valve_On_Right, ADT, Class={(300) Valve}

 

KMAT: Valve

Class Allocation: (300) Valve

 

KMAT: Valve_Terminal

Class Allocation: (300) Valve_Terminal

BOM Positions 0020-0650, Material=Valve

And we've written the following constraint:

Objects:

?VT Is_a (300) Valve_Terminal,

?V1 Is_a (300) Valve,

?V2 Is_a (300) Valve.

Condition:

Part_of (?V1, ?VT) and

Part_of (?V2, ?VT) and

?V1.Position_Number = ?V2.Position_Number - 1.

Restrictions:

?V1.Valve_On_Right = ?V2,

?V2.Valve_On_Left = ?V1.

Inferences:

?V1.Valve_On_Right,

?V2.Valve_On_Left.

As a result of this single constraint, which alone has to process up to 4,096 Valve against Valve comparisons, in order to determine adjacency, we have the ability to reference directly and immediately, from any individual Valve, to its adjacent Valve.

If you wanted to you could even do this with something called "Running Dot Notation," a facility that VB and C and C++ and C# and Java programmers (I suspect I just betrayed my own position on the "Hate Microsoft"/"Don't Hate Microsoft" divide) use all the time.

Objects:

?V Is_a (300) Valve.

Restrictions:

?V.Air_Flow_Diameter = ?V.Valve_On_Right.Air_Flow_Diameter.

Inferences:

?V.Air_Flow_Diameter,

?V.Valve_On_Right.Air_Flow_Diameter.

 

But I wouldn't recommend it, for two reasons.

 

First, if you're not careful, you end up "violating" the quaint 72 Character limitation in the Constraint Editor (something which has been inherited, for those of us with "younger" memories, from the deepest darkest recesses of the "Punchcard Age").

Secondly, it's nowhere near as obvious in the reading (and understanding) as the other alternative, from the last article:

Objects:

?V1 Is_a (300) Valve

Where

?V2 = Valve_On_Right.

Restrictions:

?V1.Air_Flow_Diameter = ?V2.Air_Flow_Diameter.

Inferences:

?V1.Air_Flow_Diameter,

?V2.Air_Flow_Diameter.

 

Speaking as someone whose own livelihood consists just as much of writing Object-oriented code, with lots of Running Dot Notation, as it does of writing Constraints, I have to admit that I find this strange. And yet it seems to be a fact. Perhaps it's worth a treatise by someone.

At any rate, all the above is what we described in the last article, and it serves as the background to this brilliant consultant's questions.

Question One:

In the Valve example you describe, the ADT seems to streamline the test for adjacency, so I only have to do this once. But your effort to simplify the example confused me a little bit. I avoid a bunch of expensive Condition tests.

But am I right in assuming that you must still declare each valve's position number? The ADT simplifies the test of adjacency, but the model must still apprehend highly specific facts about highly specific valve positions.

So V1 and V2 have to have the same diameter, but V23 and V24 might have seals on opposite ends.

Answer:

Yes, you probably do want to declare each Valve's position number. And actually, if we think about it, we need it in order for the first constraint -- the one that actually creates the ADT relationships -- to work.

But once we've done that, we've got lots of possibilities open to us. We could say, for example, that ...

Objects:

?V1 Is_a (300) Valve

Where

?V2 = Valve_On_Right.

Condition:

?V1.Position_Number = 23

Restrictions:

?V1.Seal_Position = 'LEFT',

?V2.Seal_Position = 'RIGHT'.

Inferences:

?V1.Seal_Position,

?V2.Seal_Position.

The way we get the Position Numbers onto the individual Valves, however, is not the same as it is in the regular LO-VC (or "Classical Mode").

In "Classical Mode" you would do it (or at least I would do it) by putting a Procedure on each Bill-of-Material Position, thereby setting the Position Number as soon as the BOM Position gets instantiated into the configuration.

Thus, for example, and for the very first Bill-of-Material Position:

$Self.Position_Number = 1

With Advanced Mode you have to do it in an entirely different way.

The issue, if we haven't stated it already, is that within Advanced Mode you have no procedures.

You use Constraints, or if not Constraints exactly, then things that look an awful lot like Constraints ("Rules," for example), to do everything.

Thus, instead of Procedures, you use Constraints (or Rules). And instead of Preconditions you use Constraints. And instead of Selection Conditions you use Constraints.

In other words, if we wanted to instantiate that first Valve Bill-of-Material Position in Classical Mode, we would have first had to have written a Selection Condition testing the appropriate Characteristic (or Characteristics) of the $Parent or $Root Instance.

$Parent.Do_You_Want_That_First_Valve = 'YES'

And then we would have had to have allocate it to the BOM Position, along with the Procedure setting the first Valve Position's Position Number.

In Advanced Mode, however, we do it like this:

Objects:
?VS Is_Object (Material)(300)(NR='VALVE_STACK').
Condition:
?VS.Do_You_Want_That_First_Valve = 'YES'.
Restrictions:
Has_Part
(
?VS, Pos_No = '0020' and

Pos_Type = (Material)(300)(NR='VALVE'),
WITH
Position_Number = 1
).

And instead of allocating that Constraint to a Bill-of-Material Position, we maintain it in a Constraint Net, and we allocate that Constraint Net to the Knowledgebase Object itself (rather than the Valve Stack's Configuration Profile, but that's a subject we'll save for another discussion).

This might seem awkward at first, but it has advantages. Note that everything that's normally identified by allocation within Classical Mode is now called out explicitly.

If you're one of those who believes that Product Modeling is a sophisticated form of Object-Oriented Programming, for example, then you probably think from the get-go that that's a very good thing.

Question Two:

Also, the implication is that while ADTs (advanced mode) is operational for these logical tests, standard mode is still executing for everything else. In other words, both modes can coexist in the same model. Is this true?

Answer:

No, it's not true, and I apologize if I've left that impression. A product model executing in the IPC has to be either Advanced Mode or Classical Mode. It cannot be both simultaneously.

That doesn't mean that you cannot do Classical Mode "things." I don't know of anything that you can do in Classical Mode ... from the interactive configuration point-of-view, of course ... that you can't do in Advanced Mode, although you might have to use other syntax to do it.

At any rate, once you've gone into your User Parameters and have set CFG=SCE, you will notice, when you go into transaction CU35, that the little "SCE" Checkbox up in the top-left is now active.

What happens, if you flag this Checkbox, is that the Knowledgebase Runtime Version that you generate is generated as Advanced Mode.

And that means that, if you've allocated any Preconditions or Procedures to Characteristics or Characteristic Values that are allocated to a Class within that Knowledgebase, or it you've allocated Selection Conditions or Procedures to any of the Bill-of-Material Positions that are in that Knowledgebase, they're simply ignored.

The same goes for Procedures or Constraint Nets that are allocated to the Configuration Profile of any of the Configurable Materials within the Knowledgebase.

The Knowledgebase Runtime Version Generation doesn't pick them up, and for that reason they're not included when the Knowledgebase runs in the IPC.

Question Three:

Finally, this mixed mode approach assumes execution in IPC, right?

Your introduction suggests the technology is available because IPC moves into the ECC stack, and therefore these advanced mode constraints will execute as part of standard high-level configuration process, in the IPC. But am I correct that the ADT logic simply does not execute in the R/3 VC engine?

Meaning what, that if I do execute from CU50, the constraints are simply ignored, or does the engine just crap out because of indigestible patterns?

Answer:

Yes, this approach definitely assumes execution in the IPC.

And it's also correct that the ADT logic doesn't execute in the R/3 VC engine.

The Variant Configurator doesn't "know about" the Knowledgebase Object or the Knowledgebase Runtime Version, and because it doesn't know about them, it doesn't know about any of the Dependency Nets that are allocated to them either.

It only knows about Dependency Nets that are allocated to Configuration Profiles, and since Advanced Mode Dependency Nets aren't allocated to Configuration Profiles (I wish I could say that they can't be allocated there, even by accident; but I can't, because I've never tried it), it will never "have a chance" to execute that ADT logic.

Up until a few years ago, at least, you couldn't include ADT Characteristics in Classical Mode models because the LO-VC would crap out when it found them. It thought they were UDEF's, some sort of "interesting" Characteristic that I've never gotten quite so deep into LO-VC "esoterica" to find out the meaning of, and for some reason that would cause it to crash.

But, to my surprise, when I tried it again just a little while ago the "crap out" didn't happen. So somebody either intentionally or unintentionally fixed it.

In reality, however, that's beside the point. And that's because the best rule of thumb here is probably that one should never use both Advanced Mode and Classical Mode for the interactive configuration of one and the same product model.

Either Advanced Mode or Classical Mode, but not both. No sense in complicating things.

Question Four:

You're kind of dismissive of using constraints to bring values "up", except in "counting" scenarios. But outside of SUM_PARTS, aren't constraints the only viable way to do this? Do you have a better way?

Answer:

It's ironic that I was "dismissive" about using constraints in order to bring Characteristic Values "up" from lower levels in the product structure, in scenarios other than those where one needs to do counting, because I was just in a discussion with a client where they described having to do exactly that ... for an absolutely realistic, legitimate business scenario.

So one needs to be careful. "Dismissiveness," probably, is not a very good thing.

At any rate it is absolutely true that Constraints are the only way to bring Characteristic Values "up" product structures. Procedures can bring them "down," but only from the immediate parent ($Parent) or the ultimate root ($Root), and are therefore very limited (and limiting).

The fact that Constraints can infer up, down, and across product structures, without limitation, is one of the things that differentiates them as an extraordinarily powerful modeling device.

But let's switch over to the "counting" issue, because this highlights one of the really significant benefits of using Advanced Mode.

It is true, of course, that "outside of SUM_PARTS" (which is not only very ugly, but also extremely limited), Constraints are the only viable way of doing counting.

The problem, however, is that when you're doing summing in Classical Mode, and because Constraints are declarative rather than procedural, you have to declare each object and each Characteristic that you want to get added into the sum ... and you have to declare them explicitly.

Let's say that every Valve within the Valve Terminal has Ports, and that, for some reason, we need to sum up the total number of Ports that the Valve Terminal has.

We would probably like to write a series of individual constraints like the following:

Objects:

?VT Is_a (300) Valve_Terminal,

?V Is_a (300) Valve.

Condition:

Part_Of (?V, ?VT) and ?V.Position_Number = 1.

Restrictions:

?VT.Total_Ports_Quantity =

?VT.Total_Ports_Quantity + ?V.Ports_Quantity.

Inferences:

?VT.Total_Ports_Quantity.

 

Objects:

?VT Is_a (300) Valve_Terminal,

?V Is_a (300) Valve.

Condition:

Part_Of (?V, ?VT) and ?V.Position_Number = 2.

Restrictions:

?VT.Total_Ports_Quantity =

?VT.Total_Ports_Quantity + ?V.Ports_Quantity.

Inferences:

?VT.Total_Ports_Quantity.

 

But we can't do that because we would get a conflict. The restrictions are contradictions, because they are statements of logical truth, rather than procedural execution.

Because of that, we have to do the summing like this instead (we'll restrict ourselves to a Valve Terminal with no more than four Valves, which will be enough to get the general idea):

Objects:

?VT Is_a (300) Valve_Terminal,

?V1 Is_a (300) Valve,

?V2 Is_a (300) Valve,

?V3 Is_a (300) Valve,

?V4 Is_a (300) Valve,

Condition:

Part_Of (?V1, ?VT) and ?V1.Position_Number = 1 and

Part_Of (?V2, ?VT) and ?V1.Position_Number = 2 and

Part_Of (?V3, ?VT) and ?V1.Position_Number = 3 and

Part_Of (?V4, ?VT) and ?V1.Position_Number = 4.

Restrictions:

?VT.Total_Ports_Quantity =

?V1.Ports_Quantity +

?V2.Ports_Quantity +

?V3.Ports_Quantity +

?V4.Ports_Quantity.

Inferences:

?VT.Total_Ports_Quantity.

And that's not very nice at all. Extrapolating it out to 64 Valve Positions, we see that it quickly gets very nasty indeed. From the standpoint of performance it will kill us.

Given that, and notwithstanding all of their limited (and limiting) uglinesses, some application of $Sum_Parts or $Count_Parts is probably far preferable.

But with Advanced Mode we gain a really powerful new feature. We mentioned above that, instead of Procedures and Preconditions and Selection Conditions we use Constraints, or "constraint-like things," to do everything.

And we added parenthetically that we call those "constraint-like things" Rules.

We stated above that "we would probably like to write a series of individual constraints like the following," and then we wrote some pretty straightforward but inherently contradictory constraints.

Imagine that we could do the very same thing, but even easier. Imagine that we could accomplish the summing with just one individual piece of syntax. Something like the following:

Objects:

?VT Is_a (300) Valve_Terminal,

?V Is_a (300) Valve.

Condition:

Part_Of (?V, ?VT).

Then Increment:

?VT.Total_Ports_Quantity By ?V.Ports_Quantity

Well guess what? In this case that's exactly what you can do. This single piece of code does it all.

You don't have to worry about Conflicts, because "then increment" says that you're summing. And you don't have to identify the individual Valves by Position, because it keeps track of them for you.

It's obviously very powerful, but also incredibly straightforward and "lean," when judged against the "standard" of what we all too often have to do in Classical Mode.

Conclusion

And that, probably, is the best place to draw our conclusion for this "installment."

Advanced Mode isn't only far more powerful than Classical Mode, it's also far more intuitive and straighforward ... and that's saying a lot, especially when most of us are used to having to accept the proposition that greater power comes only ... or at least mostly ... with greater complexity.

Of course one of the biggest obstacles to actually taking advantage of that power and simplicity is the fact that it's kept so well hidden.

And one of the reasons that it's kept so well hidden, apparently, is the belief that, if 1500+ SAP Variant Configurator customers are content with Classical Mode, then why show them anything different?

Obviously that's nothing but a Catch-22. People will be "content" with what they have, of course, and whatever "content" means, if they think that's all they have available.

But that's where we come back to the Conclusion from the last "installment" ...

Advanced Mode is there. It's in the system, and ... if you've got ERP2005 ... you've got it.

There's absolutely no reason ... no good reason that I can think of, at any rate ... not to take advantage of it.

Please send comments to Henk Meeter, Managing Editor, at henry.meeter@integrity-gmbh.de.