@carlschroedl Thanks for the links.
Neither respondent to my question above interpreted it the way I meant it. I kind of wish I had withdrawn the question.
I wrote, "So, a question I have is of whether to provide a way that the user could access several named slots in the volatile memory, each slot to have a complete assignment of values to parameters. The alternative would be to just have a single slot."
My current plan is just to offer a single slot and the text will probably be just a presentation in JSON of a tree format peculiar to the particular simulator.
Here is the data schema for a problem definition in the simulator. It is in a notation peculiar to my technique. Therefore, it would require verbal explanation to be understood by anybody other than me.
const model = u.Model.new(
['entities', 'VotingSystem', 'Election', 'Candidate', 'Faction', 'Slider']
The "entities" in the data model, in the sense of an entity-relationship diagram, are Voting System, Election, Candidate, (voting) Faction, and Slider.
The importance of sliders is that slider controls affect the counts of voters in voting factions. This allows the researcher to try a whole spectrum of different balances in the counts of people holding certain valuations of the possible electoral outcomes. The researcher can try different balances by manipulating the sliders. The simulator will respond as quickly as it can, to, at every moment, the most recent manipulation.
The next section just has to do with how the rest of the code can see and manipulate the problem-definition data model.
, [ 'rootConnected',
['candidates', 'Candidate'],
['factions' , 'Faction' ],
['sliders' , 'Slider' ],
['elections' , 'Election' ],
]
, ['rootConnected fixed', ['votingSystems', 'VotingSystem']]
The next section describes the many-to-one relations among the entities.
, ['||---o<', ['VotingSystem', 'votingSystem', 'elections', 'Election']]
The above says there is a one-to-many relationship between voting systems and elections. A given election follows only one voting system, and a voting system may be followed by zero to infinity elections.
, [ '>o---|| $ ||---o<',
[
'Candidate', 'candidate',
'candidateFactions', 'CandidateFaction', 'candidateFactions',
'faction', 'Faction',
],
[
'Election', 'election', 'electionFactions',
'ElectionFaction',
'electionFactions', 'faction', 'Faction',
],
[
'Faction', 'faction', 'factionSliders',
'FactionSlider',
'factionSliders', 'slider', 'Slider',
],
]
The above describes three many-to-many relationships.
There is a many-to-many relationship between candidates and factions, and the join-relation between them is called CandidateFaction. In these joint names, I stuck to alphabetical order. That is why I did not call this one, for example, FactionCandidate.
There is a many-to-many relationship between elections and factions.
There is a many-to-many relationship between factions and sliders.
The next section describes some attributes that some of the entities have.
, [ 'attributes',
['Candidate', [['name', {initValue: ""}]]],
Every candidate has a name.
['Faction', [
['name', {initValue: ""}],
['constantSizeTerm', {initValue: 1e4}],
]],
Every faction has a name and a constant size term. The size of a faction (meaning the count of voters in it) is calculated as the sum of the constant term with the products of the slider positions with coefficients recorded in the join relation between the factions and the sliders.
['CandidateFaction', [['affinity', {initValue: 0 }]]],
Each faction has an affinity toward each candidate. I normalize these, so you can use whatever scale you want.
['Slider', [
['tag', {initValue: ""}],
['value', {initValue: 0 }],
]],
Each slider has a "tag", which is basically a name. I used the term "name" for the names of persons and groups, and "tag" for inanimate things like sliders and elections. In either event, the tag or name identifies the individual thing or person.
The value field reflects the slider's current position. Zero is the middle position, -1 is the extreme left, and 1 is the extreme right. These do not necessarily represent political "left" and "right", although you can use one that way if you wish. Sliders happen to appear in a horizontal position, so "left" and "right" describe the positions of their ends relative to one another.
['FactionSlider', [['coefficient', {initValue: 0 }]]],
At the intersection of a faction and a slider, there is a field for the coefficient of the slider value for when the program is recalculating the faction size.
[ 'VotingSystem', [
['evictAllElections', { initValue: function () {
if ('VotingSystem' !== this.class.name)
throw Error("Expected a voting system.");
Array.from(this.elections).forEach( election => {
if('Election' !== election.class.name)
throw Error("Expected an election!");
election.delete()
});
},}],
Oh, well, I threw some executable code in the middle of the declaration of the schema; that probably wasn't necessary. The code is necessary, but I could have put it somewhere else in the source code, besides in the middle of the instructions to the model builder for establishing the entities and the relationships among them.
['setDefaultElections', { initValue: function () {
const election = this.class.model.Election.new({
votingSystem: this,
});
election.insert();
},}],
]],
]
);
More code.
Outside of the above exercise of notation, I also associate a single field to the problem model as a whole, and that field holds the random seed. I think the voting systems should be modeled in a deterministic manner, but the voting decision procedures (i. e. conversion from affinities to ballots) must sometimes appeal to random numbers. The use of a seeded generator makes all experiments exactly repeatable.
A data model that is constructed in conformance to an entity-relationship diagram, where many-to-many relationships are included, might not in a single, obvious, canonical way, lend itself to representation in serializable form. However, it's certainly possible to come up with several ways that one could be serialized, so that the full model could be recoverable from the serialized form.