| 1002 | */ |
| 1003 | template<class Card> |
| 1004 | VarValGraph<Card>::VarValGraph(Space& home, |
| 1005 | ViewArray<IntView>& x, ViewArray<Card>& k, |
| 1006 | int smin, int smax) |
| 1007 | : n_var(x.size()), |
| 1008 | n_val(k.size()), |
| 1009 | n_node(n_var + n_val), |
| 1010 | sum_min(smin), |
| 1011 | sum_max(smax) { |
| 1012 | |
| 1013 | vars = home.alloc<VarNode*>(n_var); |
| 1014 | vals = home.alloc<ValNode*>(n_val); |
| 1015 | |
| 1016 | for (int i = n_val; i--; ) { |
| 1017 | int kmi = k[i].min(); |
| 1018 | int kma = k[i].max(); |
| 1019 | int kc = k[i].counter(); |
| 1020 | if (kc != kma) { |
| 1021 | if (kmi >= kc) { |
| 1022 | kmi -=kc; |
| 1023 | assert(kmi >=0); |
| 1024 | } else { |
| 1025 | kmi = 0; |
| 1026 | } |
| 1027 | kma -= kc; |
| 1028 | assert (kma > 0); |
| 1029 | vals[i] = new (home) |
| 1030 | ValNode(kmi, kma, k[i].card(), i, i + n_var, kc); |
| 1031 | } else { |
| 1032 | vals[i] = new (home) |
| 1033 | ValNode(0, 0, k[i].card(), i, i + n_var, kc); |
| 1034 | } |
| 1035 | } |
| 1036 | |
| 1037 | for (int i = n_var; i--; ) { |
| 1038 | vars[i] = new (home) VarNode(i); |
| 1039 | // get the space for the edges of the varnode |
| 1040 | Edge** xadjacent = vars[i]->adj(); |
| 1041 | |
| 1042 | int j = 0; |
| 1043 | for (ViewValues<IntView> xi(x[i]); xi(); ++xi) { |
| 1044 | // get the correct index for the value |
| 1045 | while(vals[j]->val < xi.val()) |
| 1046 | j++; |
| 1047 | *xadjacent = new (home) Edge(vars[i],vals[j]); |
| 1048 | vars[i]->noe++; |
| 1049 | if (vars[i]->first() == nullptr) |
| 1050 | vars[i]->first(*xadjacent); |
| 1051 | Edge* oldprev = vars[i]->last(); |
| 1052 | vars[i]->last(*xadjacent); |
| 1053 | *vars[i]->last()->prev_ref() = oldprev; |
| 1054 | |
| 1055 | if (vals[j]->first() == nullptr) { |
| 1056 | vals[j]->first(*xadjacent); |
| 1057 | vals[j]->last(*xadjacent); |
| 1058 | } else { |
| 1059 | Edge* old = vals[j]->first(); |
| 1060 | vals[j]->first(*xadjacent); |
| 1061 | *vals[j]->first()->vnext_ref() = old; |