Further refined the last commit based on the change in definition of

a "critical property".  This lets a device define multiple critical
properties, all of which must match before additive properties can
be combined in the same device.
This commit is contained in:
Tim Edwards 2019-05-17 14:33:26 -04:00
parent f40a50d3b8
commit ee66c00121
1 changed files with 28 additions and 88 deletions

View File

@ -3704,27 +3704,6 @@ int series_optimize(struct objlist *ob1, struct nlist *tp1, int idx1,
return PropertyOptimize(obn, tp1, run1, TRUE, comb);
}
/*--------------------------------------------------------------*/
/* Combine properties of ob1 starting at property idx1 up to */
/* property (idx1 + run1) to match the properties of ob2 at */
/* idx2 to (idx2 + run2). run1 is always larger than run2. */
/*--------------------------------------------------------------*/
int series_combine(struct objlist *ob1, struct nlist *tp1, int idx1, int run1,
struct objlist *ob2, struct nlist *tp2, int idx2, int run2)
{
struct objlist *obn, *obp;
int i, j;
int changed = 0;
obn = ob1;
for (i = 0; i < idx1; i++) obn = obn->next;
obp = ob2;
for (i = 0; i < idx2; i++) obp = obp->next;
return changed;
}
typedef struct _propsort {
double value;
int idx;
@ -3842,27 +3821,6 @@ int parallel_optimize(struct objlist *ob1, struct nlist *tp1, int idx1,
return PropertyOptimize(obn, tp1, run1, FALSE, comb);
}
/*--------------------------------------------------------------*/
/* Combine properties of ob1 starting at property idx1 up to */
/* property (idx1 + run1) to match the properties of ob2 at */
/* idx2 to (idx2 + run2). run1 is always larger than run2. */
/*--------------------------------------------------------------*/
int parallel_combine(struct objlist *ob1, struct nlist *tp1, int idx1, int run1,
struct objlist *ob2, struct nlist *tp2, int idx2, int run2)
{
struct objlist *obn, *obp;
int i, j;
int changed = 0;
obn = ob1;
for (i = 0; i < idx1; i++) obn = obn->next;
obp = ob2;
for (i = 0; i < idx2; i++) obp = obp->next;
return changed;
}
/*--------------------------------------------------------------*/
/* Sort properties of ob1 starting at property idx1 up to */
/* property (idx1 + run). Use parallel critical property for */
@ -4198,20 +4156,6 @@ void PropertySortAndCombine(struct objlist *pre1, struct nlist *tp1,
ob2 = pre2->next;
}
/* Do not run parallel_combine until all other changes have been resolved */
if (changed == 0) {
if (max2 > max1)
changed += parallel_combine(ob2, tp2, idx2, max2, ob1, tp1, idx1, max1);
else if (max1 > max2)
changed += parallel_combine(ob1, tp1, idx1, max1, ob2, tp2, idx2, max2);
if (changed > 0) {
FREE(netwk1);
FREE(netwk2);
continue;
}
}
/* Case 2: Series devices with more elements in one circuit */
/* Find the largest group of series devices in circuit1 */
@ -4297,14 +4241,6 @@ void PropertySortAndCombine(struct objlist *pre1, struct nlist *tp1,
ob2 = pre2->next;
}
/* Do not run series_combine until all other changes have been resolved */
if (changed == 0) {
if (max2 > max1)
changed += series_combine(ob2, tp2, idx2, max2, ob1, tp1, idx1, max1);
else if (max1 > max2)
changed += series_combine(ob1, tp1, idx1, max1, ob2, tp2, idx2, max2);
}
FREE(netwk1);
FREE(netwk2);
@ -4341,7 +4277,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
unsigned char **clist;
struct valuelist ***vlist, *vl, *vl2, *newvlist;
proplinkptr plink, ptop;
int pcount, p, i, j, k, pmatch, ival, crit, ctype;
int pcount, p, i, j, k, pmatch, ival, ctype;
double dval;
static struct valuelist nullvl, dfltvl;
char multiple[2], other[2];
@ -4363,7 +4299,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
m_rec = NULL;
ptop = NULL;
pcount = 1;
crit = -1;
kl = (struct property *)HashFirst(&(tp->propdict));
while (kl != NULL) {
// Make a linked list so we don't have to iterate through the hash again
@ -4378,15 +4313,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
else
kl->idx = pcount++;
// Set critical property index, if there is one.
if (series == FALSE) {
if (kl->merge & MERGE_P_CRIT) crit = kl->idx;
}
else if (series == TRUE) {
if (kl->merge & MERGE_S_CRIT) crit = kl->idx;
}
kl = (struct property *)HashNext(&(tp->propdict));
}
// Recast the linked list as an array
@ -4438,11 +4364,13 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
vlist[kl->idx][i] = vl;
if (series == FALSE) {
if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR))
clist[kl->idx][i] = kl->merge & (MERGE_P_ADD | MERGE_P_PAR);
clist[kl->idx][i] = kl->merge &
(MERGE_P_ADD | MERGE_P_PAR | MERGE_P_CRIT);
}
else if (series == TRUE) {
if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR))
clist[kl->idx][i] = kl->merge & (MERGE_S_ADD | MERGE_S_PAR);
clist[kl->idx][i] = kl->merge &
(MERGE_S_ADD | MERGE_S_PAR | MERGE_S_CRIT);
}
}
}
@ -4505,11 +4433,20 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
}
}
// Critical properties can be multiplied up by M (S) and do not
// need to match. May want a more nuanced comparison, though.
if (p == crit) {
pmatch++;
continue;
// Additive properties do not need to be matched, since
// they can be combined. Critical paroperties must be
// matched. Properties with no merge behavior must match.
ctype = clist[p][i];
if (!(ctype & MERGE_S_CRIT)) {
if ((series == TRUE) && (ctype & (MERGE_S_ADD | MERGE_S_PAR))) {
pmatch++;
continue;
}
if ((series == FALSE) && (ctype & (MERGE_P_ADD | MERGE_P_PAR))) {
pmatch++;
continue;
}
}
switch(vl->type) {
@ -4598,10 +4535,10 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
}
}
// If comb == TRUE, reduce M (or S) to 1 by merging the critical
// property (if any)
// If comb == TRUE, reduce M (or S) to 1 by merging additive properties
// (if any)
if ((comb == TRUE) && (crit != -1)) {
if (comb == TRUE) {
int mult;
for (i = 0; i < run; i++) {
if (vlist[0][i] == NULL) continue;
@ -4613,11 +4550,14 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
/* combine as specified by the merge type of the property. */
for (p = 1; p < pcount; p++) {
if (p == crit) continue; /* critical properties never combine */
vl = vlist[p][i];
ctype = clist[p][i];
if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) {
/* critical properties never combine */
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) continue;
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) continue;
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
if (vl->type == PROP_INTEGER)
vl->value.ival *= mult;
else if (vl->type == PROP_DOUBLE)
@ -4625,7 +4565,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
vlist[0][i]->value.ival = 1;
changed += mult;
}
else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) {
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
/* Technically one should check if divide-by-mult */
/* reduces the value to < 1 and promote to double */
/* if so, but that's a very unlikely case. */