On-the-fly Le Chatelier

J

JKop

I have a "system", this system is 5 values:

A
B
C
D
E


Each of these values is dependant upon all others. If you want an analogy,
then take your pick:

A) Electricity: Current is proportional to Voltage, and also to Resistence

B) Gases: Volume is proportional to Pressure, and also to Temperature

So if one value changes, they all change.


Anyway, at then end of the whole design, I want my GUI to be able to just
work with it similar to the following:

cout << somesystem.GetA();
cout << somesystem.GetB();
cout << somesystem.GetC();
cout << somesystem.GetD();
cout << somesystem.GetE();


I want to create a class to represent this system. The particular class with
which the GUI will work doesn't need to have any Set functions, so the bare
minimum would be:

class SystemX
{
public:

int GetA() const;
int GetB() const;
int GetC() const;
int GetD() const;
int GetE() const;
};

or maybe even:

class SystemX
{
public:

virtual int GetA() const = 0;
virtual int GetB() const = 0;
virtual int GetC() const = 0;
virtual int GetD() const = 0;
virtual int GetE() const = 0;
};


Now... in actually implementing this system, I *could* use 5 separate
variables and update them all at precisely the moment one of them changes.
Like so:

class SystemX
{
private:

int A;
int B;
int C;
int D;
int E;

public:

int GetA() const
{
return A;
}

int GetB() const
{
return B;
}

int GetC() const
{
return C;
}

void SetA(int in_A)
{
//Super algorithm

A = in_A;

B = A + 4;
C = A / 9;
D = 42 - A;
E = A * A - 5;
}

//And the rest SetB SetC...
};


The problem with this is that it's inefficent because the values need only
be calculated when they've to be displayed.
So, moving on, I may come to:


class SystemX
{
private:

enum { aA, bB, cC, dD, eE } specified_value;

int value;

public:

void SetA(int in_A)
{
value = in_A;
specified_value = aA;
}

void SetB(int in_B)
{
value = in_B;
specified_value = bB;
}

void SetC(int in_C)
{
value = in_C:
specified_value = cC;
}

int GetA() const
{
switch ( specified_value )
{
case aA:

return value;

case bB:
//certain algorithm
case cC:
//ceratin algorithm
}
}

int GetB() const
{
switch ( specified_value )
{
case aA:
//certain algorithm
case bB:

return value;

case cC:
//certain algorithm
}

//and so on.
};


I'm not out-right saying that this is a bad method, but for the moment I'll
pursue an alternative. But.. before I get into that, I'd like advice on
splitting this class in half - I don't want the class that the GUI will work
with to even know about SetA, so would the following be advisable:

class SystemXInterface
{
public:

virtual int GetA() const = 0;
virtual int GetB() const = 0;
virtual int GetC() const = 0;
virtual int GetD() const = 0;
virtual int GetE() const = 0;
};


class SystemXImplementation : public System XInteface
{
void SetA(int); // ...
void SetB(int); // ...
}


How is this usually done? Is the above any good?


Annnnyyyyyway... at the moment, this is how my system is:


class SystemXInterface
{
protected:

int specified_value;

public:

virtual int GetA() const = 0;
virtual int GetB() const = 0;
virtual int GetC() const = 0;
virtual int GetD() const = 0;
virtual int GetE() const = 0;

void SetSpecifiedValue(int in_specified_value)
{
specified_value = in_specified_value;
}

int GetSpecifiedValue(void) const
{
return specified_value;
}

virtual ~SystemXInterface() {}
};


class SystemXImp_SpecifiedA
{
public:
virtual int GetA() const
{
return specified_value;
}

virtual int GetB() const
{
//algorithm
}

virtual int GetC() const
{
//algorithm
}

//and so on
}

class SystemXImp_SpecifiedB
{
public:
virtual int GetA() const
{
//algorithm
}

virtual int GetB() const
{
return specified_value;
}

//and so on
}


And here's how I'm interacting with it:

void DisplaySystem(SystemXInterface& intr)
{
cout << intr.GetA();
cout << intr.GetB();
cout << intr.GetC();
cout << intr.GetD();
cout << intr.GetE();

//Nice and simple!
}

int main()
{
//If you want to manipulate A, then

SystemXImp_SpecifiedA blah(567);

DisplaySystem(blah);



//If you want to manipulate D, then

SystemXIMp_SpecifiedD blah(926);

blah.SetSpecifiedValue(437);

DisplaySystem(blah);
}



Okay, so basically I'd just like all sorts of comments, questions and
suggestions. Like:

A) Should I leave the private member variable "specified_value" in my
SystemXInterface class, or should I put another class in between called
"SystemXImplementation" and put the "specified_value" in that, and then make
the following relationship:

class SystemXInterface
{
public:

virtual int GetA() const = 0;
virtual int GetB() const = 0;
virtual int GetC() const = 0;
virtual int GetD() const = 0;
virtual int GetE() const = 0;
};


class SystemXImplementation : public SystemXInterface
{
protected:

int specified_value;

public:

void SetSpecifiedValue(int in_specified_value)
{
specified_value = in_specified_value;
}

int GetSpecifiedValue(void)
{
return specified_value;
}
};

class SystemXImp_SpecifiedA : public SystemXImplementation
{
public:

virtual int GetA() const
{
return specified_value;
}

virtual int GetB() const
{
//algorithm
}

virtual int GetC() const
{
//algorithm
}
};

class SystemImp_SpecifiedB : public SystemXImplementation
{
public:

virtual int GetA() const
{
//algorithm
}

virtual int GetB() const
{
return specified_value;
}

virtual int GetC() const
{
//algorithm
}
}


Any thoughts?


B) Should I cache values? Or should I leave that up to the user. For example
if some calls GetB, and then later calls it again without the system having
changed, should I have it cached, or should I calculate it all over again,
ie. should it be built-in class behaviour or should it be the user's
problem?

C) Any other things, like how I should name my variables and classes.


Thanks!

-JKop
 
H

Howard

void SetA(int in_A)
{
//Super algorithm

A = in_A;

B = A + 4;
C = A / 9;
D = 42 - A;
E = A * A - 5;
}

//And the rest SetB SetC...
};


The problem with this is that it's inefficent because the values need only
be calculated when they've to be displayed.

If all the values can be computed from any given other value (as in your
example, where they all depend on A), then you could always simplify things
greatly by simply storing a value from which everything else can be computed
(such as A, in this example). So, for example, if the user calls SetD, then
A would be 42 - D.

One note, however: in this *specific* example, you're losing information
when calculating C from A (since they're integers, and you're dividing).
That makes the system unsymetric (?), in that there are many possible values
of A that generate a single value of C, so calling SetC would result in
nondeterministic behavior when trying to calculate A. (That is, if C is 1,
should A be 9, or 10, or 11, or...(up through 17)?) However, I'm guessing
these are just made-up examples, right? If your system does not have this
problem, then my solution would save you LOTS of effort, wouldn't it?

If you have more than one variable upon which the others depend, but which
are not themselves interdependant, then you would want to store more than
just one value. For example, using the electricty example, you're not
likely to actually change Current (I) or Power (W), but you *would* be
likely to change either Voltage (V) or Resistance (R). So you'd probably
store V and R, and calculate I and W.

But that example has a logical problem (which would exist in your solution,
too): how do you know which variable should change, if there are more than
one upon which the others depend? Say I call SetW(newW). Does that mean I
want to compute and alter R, or V? (Or both, by some other formula???)
Without more specifics, it's impossible to decide that, based solely on the
desire to change W. The interdependancy creates a paradox.

Of course, if everything depends on (can be computed from) only one specific
value, then there's no problem. Simply store that one value. Otherwise,
even given your rather complex solution, you're in a pickle. (Dill, I
think, perhaps with a hint of garlic.)

[By the way, is there actually a real problem you're trying to obtain a
solution for, or just playing with ideas? (Perhaps the answer lies in the
subject "Le Chatelier"...something about thermodynamic equilibrium, right?)]

-Howard
 
J

JKop

Howard posted:
However, I'm guessing these are just made-up
examples, right?

Correct. I should've stated that.


Of course, if everything depends on (can be computed from) only one
specific value, then there's no problem. Simply store that one value.
Otherwise, even given your rather complex solution, you're in a pickle.
(Dill, I think, perhaps with a hint of garlic.)


Yes, every other value can be calculated from one specific value, so yes, I
could just store one value.

But the thing is that the calculation details and algorithms are pretty
complicated, use a good bit of memory, and I'd lose precision if I used one
base value to calculate them all from.
[By the way, is there actually a real problem you're trying to obtain a
solution for, or just playing with ideas? (Perhaps the answer lies in
the subject "Le Chatelier"...something about thermodynamic equilibrium,
right?)]


You can apply it to pretty much anything.

In Chemistry in school, we learned it as the following:


Le Chatelier's priniciple:

When a stress is applied to a system at equilibrium, the system will
readjust to relieve the stress applied.

And we mostly applied it to chemical equilibrium.

So if you increase the temperature of a gas, the pressure goes up. If you
increase the volume of a gas the pressure goes down.


-JKop
 
D

Dave Townsend

This doesn't make sense. You seem to be omitting the possibility
that A might change, then B, etc. since once you setA then setB, you
completely lost the information about specifiedA, etc. In the type
of problem such as the gas equation PV = nRT, you need to immediately
recalculate the other variables when any of the others change.


What you might try instead is keep track of the changes on each variable,
and then only evaluate the new values when a get() is done. This might
be slighly more efficient because :

1. You may never do a get??() ever.
2. You can fold consequentive changes of one variable together, that is
setA( 1), setA(2) is equivalent to setA(2) ( well presuming that the
system depends only on the the values of A, etc, not their
derivatives,etc.
More optimistically, setA(1), setA(2), setA(1) folds down to setA(1),
and presuming the current value of A is X, setA(10), setA(X) is a nop.
3. There might be an "incremental" algorithm to recompute the new sytems
values from old ones based upon incremental differences in the independent
variables, or an iterative process to efficiently compute the new system.


With regard to implementing a system and a "GUI" helper class, I'd implement
this system class with a "dirty" flag, so as and when changes to the
independent
variables happen, I'd keep track of the sequences of changes and mark the
system
"dirty" meaning that the values will have to recomputed if anybody asks for
them.
When a get() is done, the new values are computed and dirtyflag is cleared.

Here's an outline of my idea....

#include "vector"
using namespace std;

class LeChatelier
{
public:
LeChatelier( int P , int V, int T, int N )
:_P(P), _V(V), _T(T), _N(N),
_dirty(false)
{}


public:
void setP( int P)
{
_dirty = true;
changes.push_back( change(P, 'P'));
}
void setV( int V)
{
_dirty = true;
changes.push_back( change(V, 'V'));
}
void setT( int T)
{
_dirty = true;
changes.push_back( change(T, 'T'));
}
void setN( int N )
{
_dirty = true;
changes.push_back( change(N, 'N'));
}


int getP()
{
if (_dirty)
updateValues();
return _P;
}
int getV()
{
if (_dirty)
updateValues();
return _V;
}
int getT()
{
if (_dirty)
updateValues();
return _T;
}
int getN()
{
if (_dirty)
updateValues();
return _N;
}


private:
int _P;
int _V;
int _T;
int _N;

bool _dirty;

struct change
{
int _value;
char _variable;

change( int value, char variable)
:_value(value), _variable(variable)
{}
change( const change& c )
:_value(c._value), _variable(c._variable)
{}

};

vector< change > changes;


void updateValues()
{
for (int i=0; i< changes.size(); ++i )
{
switch( changes._variable)
{
case 'P':
compute_from_P(changes._value );
break;
case 'V':
compute_from_V(changes._value );
break;
case 'T':
compute_from_T(changes._value);
break;
case 'N':
compute_from_N(changes._value);
break;

}


}
// purge change list and start over.
changes.clear();
_dirty=false;

}
void compute_from_P( int P )
{
// magic happens here...to update new values.

_P = P;

}
void compute_from_V( int V )
{

// magic happens here...to update new values.

_V=V;


}
void compute_from_T( int T )
{

// magic happens here...to update new values.

_T=T;


}
void compute_from_N( int N )
{

// magic happens here...to update new values.

_N=N;


}

};



int main(int argc, char* argv[])
{
LeChatelier lechatelier( 10, 11, 34, 30);

lechatelier.setP(20);
lechatelier.setP(25);
lechatelier.setT(400);
lechatelier.setV(22);

int newP = lechatelier.getP();
int newT = lechatelier.getT();
int newV = lechatelier.getV();

return 0;
}


A simple wrapper class for this object can be used by a GUI, the wrapper
class merely
forwarding calls to the gettters() in the system class.
 
D

David Rubin

JKop said:
I have a "system", this system is 5 values: [snip]
Each of these values is dependant upon all others. [snip]
Anyway, at then end of the whole design, I want my GUI to be able to just
work with it similar to the following:

cout << somesystem.GetA();
cout << somesystem.GetB();
cout << somesystem.GetC();
cout << somesystem.GetD();
cout << somesystem.GetE();

This is a rqeuirement: provide accessors for each value.
I want to create a class to represent this system. The particular class with
which the GUI will work doesn't need to have any Set functions, so the bare
minimum would be:

[snip - only accessors]
You have to distinguish between *doesn't* *need* and *shouldn't* *be*
*able* *to*. Also, you need to determine whether or not you need a
protocol (abstract) class, or if you can just use a concrete class.
These decisions should be driven by your problem domain, expected
reuse of your classes, and the degree of insulation you want or need
to provide to clients of your classes.
Now... in actually implementing this system, I *could* use 5 separate
variables and update them all at precisely the moment one of them changes.

[snip - or I could calculate the values on demand, cache values, etc]

It's difficult to give advise about these kinds of optimizations
without knowing more details about the system you are implementing.
Just do something simple, and then do some performance testing later.
If you separate your implementation from your class definition (i.e.,
in a separate .c file), you can change the implementation at any time
without causing your clients to recompile.

As far as style issues go, just pick something that makes sense and
*be* *consistent*.

/david
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,172
Messages
2,570,934
Members
47,477
Latest member
ColumbusMa

Latest Threads

Top