0% found this document useful (0 votes)
30 views20 pages

КОД

The document discusses a method for synthesizing topologies to increase the fault tolerance of distributed systems. It includes code for a Digit class that represents numeric digits, as well as interfaces and classes for numeric systems, alphabets, and code sequences.

Uploaded by

таня
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views20 pages

КОД

The document discusses a method for synthesizing topologies to increase the fault tolerance of distributed systems. It includes code for a Digit class that represents numeric digits, as well as interfaces and classes for numeric systems, alphabets, and code sequences.

Uploaded by

таня
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

Метод синтезу топологій для підвищення

відмовостійкості розподілених систем

Лістинг програми
public class Digit implements Comparable<Digit> {
int value;
String glyph;

public Digit(int value) {


this.value = value;
if ((value >= 0) && (value < 10)) glyph = String.valueOf(value);
else glyph = "(" + value + ")";
}

public Digit(int value, String glyph) {


this.value = value;
this.glyph = glyph;
}

public int getValue() {return value;}


public String getGlyph() {return glyph;}

public static int getValueOf(@NotNull String s) throws


NumberFormatException {
if (s.length() == 1) {
return Integer.valueOf(s);
} else {
String[] v = s.split("\\(\\)");
for (String str : v) {
if (str.isEmpty()) continue;
try {
int num = Integer.valueOf(str);
return num;
} catch (NumberFormatException e) {
continue;
}
}
throw new NumberFormatException("Incorrect format of digit");
}
}

@Nullable
public static Digit create(@NotNull String s) {
return new Digit(getValueOf(s), s);
}

@Override
public boolean equals(Object obj) {
if (obj.getClass().isAssignableFrom(Digit.class)) {
Digit d = (Digit) obj;
return d.value == getValue() &&
d.getGlyph().equalsIgnoreCase(getGlyph());
}
return super.equals(obj);
}

public boolean equalValue(@NotNull Digit obj) {


return obj.getValue() == getValue();
}
@Override
public int compareTo(@NotNull Digit digit){return this.value -
digit.value;}
@Override
public String toString() { return glyph; }

public static Comparator<Digit> getComparator() {


return Comparator.comparingInt(Digit::getValue);
}
}

public interface Alphabet {


int getSize();
@NotNull
Collection<Digit> getDigits();
@Nullable
Digit get(int value);
@Nullable
Digit get(String glyph);

default int maxValue(){


return Operations.operate(
(o1, o2) -> Math.max(o1 == null ? 0: o1, o2.getValue()),
getDigits());
}
default int minValue(){
return Operations.operate(
(o1, o2) -> Math.min(o1 == null ? 0: o1, o2.getValue()),
getDigits());
}

default boolean contains(int value){return get(value) != null;}


default boolean contains(String glyph){return get(glyph) != null;}
default boolean contains(Digit digit){
Collection<Digit> digits = getDigits();
for (Digit d:digits) { if (d.equals(digit)) return true; }
return false;
}
boolean equals(Object other);
}

public class ClassicAlphabet implements Alphabet {


List<Digit> digits = new ArrayList<>();
int minValue, maxValue;

public ClassicAlphabet(List<Digit> digits) {this.digits = digits;init();}


public ClassicAlphabet(Digit... digits) { this(Arrays.asList(digits)); }
@Override
public int getSize() { return digits.size(); }
@Override
public Collection<Digit> getDigits() {return digits;}
@Override
public Digit get(int value) {
for (Digit d:digits) {if (d.getValue() == value) return d;}
return null;
}

@Override
public Digit get(String glyph) {
for (Digit d:digits) {if (d.getGlyph().equalsIgnoreCase(glyph))
return d;}
return null;
}

protected void init(){


this.maxValue = Operations.operate(
(o1, o2) -> Math.max(o1 == null ? 0: o1, o2.getValue()),
getDigits()
);
this.minValue = Operations.operate(
(o1, o2) -> Math.min(o1 == null ? 0: o1, o2.getValue()),
getDigits()
);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassicAlphabet)) return false;
ClassicAlphabet that = (ClassicAlphabet) o;
if (minValue != that.minValue) return false;
if (maxValue != that.maxValue) return false;
return getDigits() != null ? getDigits().equals(that.getDigits()) :
that.getDigits() == null;
}
@Override
public int hashCode() {
int result = getDigits() != null ? getDigits().hashCode() : 0;
result = 31 * result + minValue;
result = 31 * result + maxValue;
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("[[ ");
for (Digit d:digits) {

sb.append(d.getGlyph()).append('(').append(d.getValue()).append(')');
}
sb.append(" ]]");
return sb.toString();
}
@Override
public int maxValue() { return maxValue; }
@Override
public int minValue() { return minValue; }
}

public interface NumericSystem {


int getWeights(int i);
Alphabet getAlphabet(int i);
boolean isRegular();
default Digit sum(int d1, int d2, int position, Container<Integer>
residue){
Alphabet alphabet = getAlphabet(position);
int sum = d1 + d2;
Digit res = alphabet.get(sum);
if (res != null){
residue.setContained(0);
return res;
}else{
int min = alphabet.minValue();
int max = alphabet.maxValue();
res = sum<min ? alphabet.get(min) : alphabet.get(max);
residue.setContained(sum - res.getValue());
return res;
}
}

default Digit sum(Digit d1, Digit d2, int position, Container<Integer>


residue){return sum(d1.getValue(), d2.getValue(), position, residue);}

default Collection<CodeSequence> generateAll(int size){


List<List<Digit>> codes = new ArrayList<>();
List<List<Digit>> next = new ArrayList<>();
for (int i = 0; i < size; i++) {
Collection<Digit> alpha = getAlphabet(i).getDigits();
if (i==0){
for (Digit d:alpha){
List<Digit> var = new ArrayList<>();
var.add(d);
next.add(var);
}
}else{
for (List<Digit> code:codes) {
for (Digit d:alpha){
List<Digit> var = new ArrayList<>();
var.addAll(code);
var.add(d);
next.add(var);
}
}
}
codes = next;
next = new ArrayList<>();
}
List<CodeSequence> seq = new ArrayList<>();
for (List<Digit> code:codes) {seq.add(new CodeSequence(code));}
return seq;
}
boolean equals(Object other);
static NumericSystem createRegular(Alphabet alphabet, int radix){
return radix == 2 ? new BinaryNS(alphabet) : new
HomogeneousNS(alphabet, radix);
}
}

public class CodeSequence {


List<Digit> code = new ArrayList<>();

public CodeSequence() { }
public CodeSequence(List<Digit> code) { this.code = code; }
public CodeSequence(Digit... digits)
{this(Arrays.asList(reverse(digits)));}
public int size(){return this.code.size();}
public boolean isEmpty(){return this.code.isEmpty();}
public Digit get(int index){return this.code.get(index);}
public Digit getLower(){ return this.code.get(0);}
public Digit getHigher() { return this.code.get(this.size()-1);}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
for (Digit d:code) { sb.append(d); }
return sb.reverse().toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof CodeSequence)) return false;
CodeSequence that = (CodeSequence) o;
for (int i = 0; i < size(); i++) {
if (!that.get(i).equals(this.get(i))) return false;
}
return true;
}
@Override
public int hashCode() {return code.hashCode();}
public List<Digit> values(){ return copy(this.code); }
public CodeSequence copy(){ return new CodeSequence(this.values()); }
public CodeSequence copy(int from, int to){ return new
CodeSequence(copy(this.code, from, to)); }
public CodeSequence copyHigher(int from){ return copy(from, size()); }
public CodeSequence copyLower(int to){ return copy(0, to); }
public CodeSequence[] split(int point){ return split(this, point); }
public CodeSequence concat(CodeSequence higherPart){ return concat(this,
higherPart); }
public CodeSequence addLower(Digit d){ return addLower(this, d); }
public CodeSequence addHigher(Digit d){ return addHigher(this, d); }
public CodeSequence addLower(Digit... d){ return concat(new
CodeSequence(d), this); }
public CodeSequence addHigher(Digit... d){ return concat(this, new
CodeSequence(d)); }
public CodeSequence exchange(Digit d, int index){return exchange(this, d,
index);}
public CodeSequence swap(int i, int j){return swap(this, i, j);}
public CodeSequence reverse(){ return reverse(this);}
public CodeSequence shiftLeft(){ return shiftLeft(this); }
public CodeSequence shiftRight(){ return shiftRight(this); }
public CodeSequence shiftLeft(Digit insertion){ return shiftLeft(this,
insertion); }
public CodeSequence shiftRight(Digit insertion){ return shiftRight(this,
insertion); }

//--------------------------------------------------------------
//COPY
public static List<Digit> copy(List<Digit> src){
List<Digit> dest = new ArrayList<>(src.size());
dest.addAll(src);
return dest;
}
public static List<Digit> copy(List<Digit> src, int from, int to){
List<Digit> dest = new ArrayList<>(src.size());
for (int i = from; i < to; i++)
if ((i>=0)&&(i<src.size()))
dest.add(src.get(i));
return dest;
}
//CONCATENATION
public static CodeSequence concat(CodeSequence lowerPart, CodeSequence
higherPart){
CodeSequence cs = lowerPart.copy();
cs.code.addAll(higherPart.code);
return cs;
}
public static CodeSequence concat(List<Digit> lowerPart, List<Digit>
higherPart){
CodeSequence cs = new CodeSequence(lowerPart);
cs.code.addAll(higherPart);
return cs;
}
public static CodeSequence addHigher(CodeSequence sequence, Digit d){
CodeSequence cs = sequence.copy();
cs.code.add(d);
return cs;
}
public static CodeSequence addLower(CodeSequence sequence, Digit d){
CodeSequence cs = new CodeSequence();
cs.code.add(d);
cs.code.addAll(sequence.code);
return cs;
}
//SPLIT
public static CodeSequence[] split(CodeSequence sequence, int point){
return new CodeSequence[]{sequence.copyLower(point),
sequence.copyHigher(point)};
}
//EXCHANGE
public static CodeSequence exchange(CodeSequence src, Digit d, int index)
{
CodeSequence cs = src.copy();
if ((index<0)||(index>=src.size())) return cs;
else{
cs.code.set(index, d);
return cs;
}
}
//SWAP
public static CodeSequence swap(CodeSequence src, int i, int j){
CodeSequence cs = src.copy();
if ((i<=0)||(i>=src.size())) return cs;
if ((j<=0)||(j>=src.size())) return cs;
else{
cs.code.set(i, src.get(j));
cs.code.set(j, src.get(i));
return cs;
}
}
//SHIFT
public static CodeSequence shiftLeft(CodeSequence sequence){
return shiftLeft(sequence, sequence.getHigher());
}
public static CodeSequence shiftRight(CodeSequence sequence){
return shiftRight(sequence, sequence.getLower());
}
public static CodeSequence shiftLeft(CodeSequence sequence, Digit
insertion){
CodeSequence cs = sequence.copyLower(sequence.size()-1);
return cs.addLower(insertion);
}
public static CodeSequence shiftRight(CodeSequence sequence, Digit
insertion){
CodeSequence cs = sequence.copyHigher(1);
return cs.addHigher(insertion);
}

//REVERSE
@Contract(pure = true)
public static Digit[] reverse(Digit[] sequence){
Digit[] narr = new Digit[sequence.length];
for (int i = 0; i < sequence.length; i++) {
narr[i] = sequence[sequence.length - i - 1];
}
return narr;
}

public static List<Digit> reverse(List<Digit> sequence){


List<Digit> narr = new ArrayList<>(sequence.size());
for (int i = 0; i < sequence.size(); i++) {
narr.set(i, sequence.get(sequence.size() - i - 1));
}
return narr;
}
@NotNull
public static CodeSequence reverse(CodeSequence sequence){
return new CodeSequence(reverse(sequence.code));
}
//COLLECTION TO STRING
static String toString(Collection<CodeSequence> sequences, String
delimiter){
StringBuilder sb = new StringBuilder();
for (CodeSequence s:sequences) {
sb.append(s).append(delimiter);
}
return sb.toString();
}
}

public interface Code {


CodeSequence getSequence();
NumericSystem getNumericSystem();
default int getValue(){return getValue(getSequence(),
getNumericSystem());}
default boolean isCorrect(){return isCorrect(getSequence(),
getNumericSystem());}
default boolean isRegular(){return getNumericSystem().isRegular();}
boolean equals(Object other);
int hashCode();
String toString();
static int getValue(CodeSequence sequence, NumericSystem ns){
int value = 0;
for (int i = 0; i < sequence.size(); i++) {
value += sequence.get(i).getValue()*ns.getWeights(i);
}
return value;
}
static boolean isCorrect(CodeSequence sequence, NumericSystem ns){
for (int i = 0; i < sequence.size(); i++) {
if (!ns.getAlphabet(i).contains(sequence.get(i))) return false;
}
return true;
}
static Code create(CodeSequence sequence, NumericSystem ns){
if (ns.getClass().isAssignableFrom(HomogeneousNS.class))
return new RegularCode(sequence, (HomogeneousNS) ns);
else return new GenericCode<>(sequence, ns);
}
static Collection<Code> convert(Collection<CodeSequence> sequences,
NumericSystem ns){
Collection<Code> codes = new ArrayList<>(sequences.size());
for (CodeSequence s:sequences) {codes.add(create(s, ns));}
return codes;
}
static Collection<CodeSequence> convert(Collection<Code> codes){
Collection<CodeSequence> sequences = new ArrayList<>(codes.size());
for (Code c:codes) { sequences.add(c.getSequence());}
return sequences;
}
static String toString(Collection<Code> sequences, String delimiter){
StringBuilder sb = new StringBuilder();
for (Code s:sequences)
{sb.append(s.getSequence()).append(delimiter);}
return sb.toString();
}
static Collection<Code> toCorrect(Collection<Code> codes){
Collection<Code> res = new ArrayList<>(codes.size());
for (Code c:codes) {if (c.isCorrect()) res.add(c);}
return res;
}
class GenericCode<NS extends NumericSystem> implements Code{
CodeSequence sequence;
NS numericSystem;
public GenericCode(CodeSequence sequence, NS numericSystem) {
this.sequence = sequence; this.numericSystem = numericSystem;
}
@Override
public CodeSequence getSequence() {return sequence;}
@Override
public NumericSystem getNumericSystem() { return numericSystem;}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GenericCode)) return false;
GenericCode<?> that = (GenericCode<?>) o;
return getSequence().equals(that.getSequence()) &&
getNumericSystem().equals(that.getNumericSystem());
}
@Override
public int hashCode() {
int result = getSequence().hashCode();
result = 31 * result + getNumericSystem().hashCode();
return result;
}

public String toString(){return "["+getSequence().toString()+"]"; }


}
class RegularCode extends GenericCode<HomogeneousNS> {
public RegularCode(CodeSequence sequence, HomogeneousNS ns) {
super(sequence, ns);
}
public String toString(){
return "["+getSequence().toString()+"]"+
((HomogeneousNS)getNumericSystem()).getRadix();
}
}
}
public class HomogeneousNS implements NumericSystem {
Alphabet alphabet;
int radix;
public HomogeneousNS(Alphabet alphabet, int radix) {
this.alphabet = alphabet;this.radix = radix;
}
@Override
public int getWeights(int i) {return (int) Math.pow(radix, i); }
@Override
public Alphabet getAlphabet(int i) {return alphabet;}
@Override
public boolean isRegular() { return true; }
public Alphabet getAlphabet() { return alphabet; }
public int getRadix() { return radix; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof HomogeneousNS)) return false;
HomogeneousNS that = (HomogeneousNS) o;
if (getRadix() != that.getRadix()) return false;
return getAlphabet() != null ?
getAlphabet().equals(that.getAlphabet()) :
that.getAlphabet() == null;
}
@Override
public int hashCode() {
int result = getAlphabet() != null ? getAlphabet().hashCode() : 0;
result = 31 * result + getRadix();
return result;
}
}
public class BinaryNS extends HomogeneousNS {
public BinaryNS(Alphabet alphabet) {super(alphabet, 2);}
public BinaryNS(Digit[] alpha){super(new ClassicAlphabet(alpha), 2);}
@Override
public int getWeights(int i) {if (i<0) return 0; return 1 << i; }
}
public interface Function<T> {
T exec(@NotNull T data, Object... args);
interface CodeFunction<CODE extends Code> extends Function<CODE>{}
interface DigitalFunction<DIGIT extends Digit> extends Function<DIGIT>{}
interface SequentialFunction<SEQ extends CodeSequence> extends
Function<SEQ>{}
class DigitalExchange<DIGIT extends Digit> implements
DigitalFunction<DIGIT>{
@Override
public DIGIT exec(@NotNull DIGIT data, Object... args) {
HashMap<DIGIT, DIGIT> func = Operations.cast(args, 0,
HashMap.class, new HashMap());
return func == null ? data : func.getOrDefault(data, data);
}
}
class SequentialExchange implements SequentialFunction<CodeSequence> {
@Override
public CodeSequence exec(@NotNull CodeSequence data, Object... args)
{
if (data.isEmpty()) return data;
Integer pos = Operations.cast(args, 0, Integer.class, 0);
Digit exchanger = Operations.cast(args, 0, Digit.class,
data.get(pos));
return data.exchange(exchanger, pos);
}
}
class SequentialShuffle implements SequentialFunction<CodeSequence>{
@Override
public CodeSequence exec(@NotNull CodeSequence data, Object... args)
{
if (data.isEmpty()) return data;
Boolean left = Operations.cast(args, 0, Boolean.class, false);
Digit insertion = Operations.cast(args, 1, Digit.class, null);
Container<Digit> container =
Operations.cast(args, 2, Container.class,null);
return exec(data, left, insertion, container);
}

public CodeSequence exec(@NotNull CodeSequence data, boolean left,


Digit insertion, Container<Digit> container){
Digit carry = left ? data.getHigher() : data.getLower();
if (insertion == null) insertion = carry;
if (container != null) container.setContained(carry);
return left ? data.shiftLeft(insertion) :
data.shiftRight(insertion);
}
}
class DigitalSum implements DigitalFunction<Digit>{
@Override
public Digit exec(@NotNull Digit data, Object... args) {
Digit digit = Operations.cast(args, 0, Digit.class,
NSDefaults.D_0);
NumericSystem ns = Operations.cast(args, 1, NumericSystem.class,
NSDefaults.NS_BIN);
int pos = Operations.cast(args, 2, Integer.class, 0);
Container container =
Operations.cast(args, 3, Container.class,new
SimpleContainer<>());
return ns.sum(data, digit, pos, container);
}
}
}
public interface AllFunction<T> {
Collection<T> exec(T data, Object... args);
interface SequentialAllFunction<SEQ extends CodeSequence> extends
AllFunction<SEQ>{}
interface CodeAllFunction<CODE extends Code> extends AllFunction<CODE>{}
class AF_Exchange implements CodeAllFunction<Code>{
@Override
public Collection<Code> exec(Code data, Object... args) {
Integer pos = Operations.cast(args, 0, Integer.class, 0);
return exec(data, pos);
}
public Collection<Code> exec(Code data, int pos){
Collection<Code> result = new ArrayList<>();
NumericSystem ns = data.getNumericSystem();
Alphabet alphabet = ns.getAlphabet(pos);
for (Digit d:alphabet.getDigits()) {
result.add(Code.create(data.getSequence().exchange(d, pos),
ns));
}
return result;
}
}
class AF_Shift implements CodeAllFunction<Code>{
@Override
public Collection<Code> exec(Code data, Object... args) {
return exec(data);
}
public Collection<Code> exec(Code data){
Collection<Code> result = new ArrayList<>();
NumericSystem ns = data.getNumericSystem();
Alphabet alphabet = ns.getAlphabet(0);
if (alphabet == null) return result;
for (Digit d:alphabet.getDigits()) {
result.add(Code.create(data.getSequence().shiftLeft(d), ns));
result.add(Code.create(data.getSequence().shiftRight(d),
ns));
}
return result;
}
}
}
public interface Links<ID> {
//nodes
default int getN(){return getIDs().size();}
List<ID> getIDs();
boolean isPossibleToAdd(ID id);
default boolean isPossibleToAdd(ID... ids){
for (ID id:ids) if (!isPossibleToAdd(id)) return false;
return true;
}
default boolean isPossibleToAdd(Collection<ID> ids){
for (ID id:ids) if (!isPossibleToAdd(id)) return false;
return true;
}
boolean isPossibleToRemove(ID id);
default boolean isPossibleToRemove(ID... ids){
for (ID id:ids) if (!isPossibleToRemove(id)) return false;
return true;
}
//forced methods
void forcedAdd(ID id);
void forcedRemove(ID id);

//methods for nodes


default void add(ID id){ if (isPossibleToAdd(id)) forcedAdd(id); }
default void add(ID... ids){
if (!isPossibleToAdd(ids)) return;
for (ID id:ids) { forcedAdd(id); }
}
default void add(Collection<ID> ids){
if (!isPossibleToAdd(ids)) return;
for (ID id:ids) { forcedAdd(id); }
}
default void remove(ID id){if (isPossibleToRemove(id)) forcedRemove(id);}
default void remove(ID... ids){
if (!isPossibleToRemove(ids)) return;
for (ID id:ids) { forcedRemove(id); }
}

//methods for links


boolean hasLink(ID id, ID to);
Set<ID> getInputs(ID id);
Set<ID> getOutputs(ID id);
default Set<ID> getLinks(ID id){
Set<ID> set = getInputs(id);
set.addAll(getOutputs(id));
return set;
}
void link(ID id, ID to);
default void link(ID id, ID... to){ for (ID t:to) link(id, t); }
default void link(ID id, Collection<ID> to){for (ID t:to) link(id, t);}
void unlink(ID id, ID to);
default void unlink(ID id, ID... to){for (ID t:to) unlink(id, t);}
default void unlink(ID id, Collection<ID> to){for (ID t:to) unlink(id,
t);}
default void unlinkInputs(ID id){ unlink(id, getInputs(id)); }
default void unlinkOutputs(ID id){ unlink(id, getOutputs(id));}
default void unlinkAll(ID id){unlinkInputs(id);unlinkOutputs(id);}
void clear();
void clearLinks();
default int linkToMatrix(ID id, ID to){ return hasLink(id, to) ? 1 : 0; }
default void linkFromMatrix(ID id, ID to, int w){ if (w!=0) link(id, to);
}
default int[][] toMatrix(List<ID> ids){
int N = getN();
int[][] matrix = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[i][j] = linkToMatrix(ids.get(i), ids.get(j));
}
}
return matrix;
}
default void fromMatrix(int[][] data, List<ID> ids){
clear();
add(ids);
int N = ids.size();
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
linkFromMatrix(ids.get(i), ids.get(j), data[i][j]);
}
}
public interface FatLinks<ID> extends Links<ID> {
int getLink(ID id, ID to);
void link(ID id, ID to, int weight);
HashMap<ID, Integer> getInputWeights(ID id);
HashMap<ID, Integer> getOutputWeights(ID id);
@Override
default void link(ID id, ID to) { link(id, to, 1);}
@Override
default void unlink(ID id, ID to){ link(id, to, 0);}
@Override
default boolean hasLink(ID id, ID to) { return getLink(id, to)==0; }
@Override
default Set<ID> getInputs(ID id) { return getInputWeights(id).keySet(); }
@Override
default Set<ID> getOutputs(ID id) { return getOutputWeights(id).keySet();
}
@Override
default int linkToMatrix(ID id, ID to) { return getLink(id, to); }
@Override
default void linkFromMatrix(ID id, ID to, int w) { link(id, to, w); }
}
public interface IndirectedLinks<ID> extends Links<ID> {
boolean hasMonoLink(ID id, ID to);
void addMonoLink(ID id, ID to);
void removeMonoLink(ID id, ID to);

@Override
default boolean hasLink(ID id, ID to) {
return hasMonoLink(id, to) || hasMonoLink(to, id);
}
@Override
default void link(ID id, ID to) {
addMonoLink(id, to);addMonoLink(to, id);
}
@Override
default void unlink(ID id, ID to) {
removeMonoLink(id, to);removeMonoLink(to, id);
}
}
public interface IndirectedFatLinks<ID> extends IndirectedLinks<ID>,
FatLinks<ID> {
int getMonoLink(ID id, ID to);
void addMonoLink(ID id, ID to, int weight);
@Override
default boolean hasMonoLink(ID id, ID to) { return getMonoLink(id, to) !=
0; }
@Override
default void addMonoLink(ID id, ID to) { addMonoLink(id, to, 1); }
@Override
default void removeMonoLink(ID id, ID to) { addMonoLink(id, to, 0); }
@Override
default boolean hasLink(ID id, ID to) {
return hasMonoLink(id, to) || hasMonoLink(to, id);
}
@Override
default int getLink(ID id, ID to) {
return Math.max(getMonoLink(id, to), getMonoLink(to, id));
}
@Override
default void link(ID id, ID to) {
addMonoLink(id, to, 1);addMonoLink(to, id, 1);
}
@Override
default void link(ID id, ID to, int weight) {
addMonoLink(id, to, weight);addMonoLink(to, id, weight);
}
@Override
default void unlink(ID id, ID to) {
addMonoLink(id, to, 0);addMonoLink(to, id, 0);
}
@Override
default HashMap<ID, Integer> getInputWeights(ID id) {
HashMap<ID, Integer> map = new HashMap<>();
for (ID from:getIDs()) {
int w = getMonoLink(from, id);
if (w != 0) map.put(from, w);
}
return map;
}
@Override
default HashMap<ID, Integer> getOutputWeights(ID id) {
HashMap<ID, Integer> map = new HashMap<>();
for (ID to:getIDs()) {
int w = getMonoLink(id, to);
if (w != 0) map.put(to, w);
}
return map;
}
default HashMap<ID, Integer> getWeights(ID id){
HashMap<ID, Integer> map = new HashMap<>();
for (ID target:getIDs()) {
int w = getLink(id, target);
if (w != 0) map.putIfAbsent(target, w);
}
return map;
}
@Override
default Set<ID> getLinks(ID id) {return getWeights(id).keySet();}
@Override
default void unlinkAll(ID id) { unlink(id, getLinks(id)); }
}
ublic abstract class MappedGraph<ID, V> implements Links<ID> {
protected HashMap<ID, V> links = new HashMap<>();
protected LinkedList<ID> ids = new LinkedList<>();
public MappedGraph() { }
public MappedGraph(Collection<ID> ids) { this.ids.addAll(ids); }
@Override
public int getN() { return ids.size(); }
@Override
public List<ID> getIDs() { return ids; }
@Override
public boolean isPossibleToAdd(ID id) { return !ids.contains(id); }
@Override
public boolean isPossibleToRemove(ID id) { return ids.contains(id); }
@Override
public void forcedAdd(ID id) { ids.addLast(id); }
@Override
public void forcedRemove(ID id) {unlinkAll(id);ids.remove(id);}
@Override
public void clear() {links.clear();ids.clear();}
@Override
public void clearLinks() { links.clear(); }
}
public class Topology<ID> extends MappedGraph<ID, HashMap<ID, Integer>>
implements IndirectedFatLinks<ID> {
public Topology() { }
public Topology(Collection<ID> ids) { super(ids); }
@Override
public int getMonoLink(ID id, ID to) {
return links.getOrDefault(id, new HashMap<>()).getOrDefault(to, 0);
}
@Override
public void addMonoLink(ID id, ID to, int weight) {
if (id.equals(to)) return;
HashMap<ID, Integer> map = links.getOrDefault(id, new HashMap<>());
map.put(to, weight);
links.putIfAbsent(id, map);
}
@Override
public void removeMonoLink(ID id, ID to) {
if (id.equals(to)) return;
if (!links.containsKey(id)) return;
HashMap<ID, Integer> map = links.get(id);
if (!map.containsKey(to)) return;
map.remove(to);
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("IDs: {").append(PConsole.collectionToStr(getIDs(),
";")).append("}\n");
sb.append("Links:\n").append(PConsole.deepMapToString(links, "\n", "-
>\t", "; ", "="));
return sb.toString();
}
}
public interface TopologyParametrizer<ID> {
Links<ID> topo();
default HashMap<ID, Integer> getDegrees(){
HashMap<ID, Integer> degrees = new HashMap<>();
for (ID id:topo().getIDs()) {
degrees.put(id, topo().getLinks(id).size());
}
return degrees;
}
default int getLinkAsDistance(ID id, ID to){return 1;}
default HashMap<ID, HashMap<ID, Integer>> getDistances(){
HashMap<ID, HashMap<ID, Integer>> dist = new HashMap<>();
for (ID id:topo().getIDs()) {
dist.put(id, getDistances(id));
}
return dist;
}
default HashMap<ID, Integer> getDistances(ID id){
HashMap<ID, Integer> map = new HashMap<>();
Set<ID> nexts = new HashSet<>(), next2 = new HashSet<>();
map.put(id, 0);
nexts.add(id);
while (!nexts.isEmpty()){
for (ID n:nexts) {
Set<ID> outs = topo().getOutputs(n);
int dist = map.get(n);
for (ID to:outs) {
int ndist = dist + getLinkAsDistance(n, to);
int pdist = map.getOrDefault(to, Integer.MAX_VALUE);
if (ndist<pdist){
map.put(to, ndist);
next2.add(to);
}
}
}
nexts = next2;
next2 = new HashSet<>();
}
if(map.size() < topo().getN()){
for (ID k:topo().getIDs()) {
map.putIfAbsent(k, Integer.MAX_VALUE);
}
}
return map;
}
default int getMax(HashMap<ID, Integer> map){
return Collections.max(map.values());
}

default int getSum(HashMap<ID, Integer> map){


int sum = 0;
boolean inf = false;
for (ID id:map.keySet()){
int t = map.get(id);
inf |= t == Integer.MAX_VALUE;
sum += t;
}
return inf ? Integer.MAX_VALUE : sum;
}

default HashMap<ID, Integer> getEccentricities(HashMap<ID, HashMap<ID,


Integer>> distances){
HashMap<ID, Integer> ecc = new HashMap<>();
for (ID id:distances.keySet()) {
ecc.put(id, getMax(distances.get(id)));
}
return ecc;
}

default int getDiameter(HashMap<ID, HashMap<ID, Integer>> dists){


return getMax(getEccentricities(dists));
}
default int getSummaryDistances(HashMap<ID, HashMap<ID, Integer>>
distances){
int sum = 0;
boolean inf = false;
for (ID id:distances.keySet()){
int t = getSum(distances.get(id));
inf |= t == Integer.MAX_VALUE;
sum += t;
}
return inf ? Integer.MAX_VALUE : sum;
}
default double getMiddleDiameter(HashMap<ID, HashMap<ID, Integer>>
distances){
return getMiddleDiameter(getSummaryDistances(distances));
}
default double getMiddleDiameter(double summaryDist){
return summaryDist/(topo().getN()*(topo().getN()-1));
}
default double getTraffic(double middleDiameter, int degree){
return 2*middleDiameter/degree;
}
}
public class BufferedParametrizer<ID> implements TopologyParametrizer<ID> {
Links<ID> links;
HashMap<ID, Integer> degrees = new HashMap<>();
HashMap<ID, HashMap<ID, Integer>> distances = new HashMap<>();
double summaryDist = 0;
public BufferedParametrizer(Links<ID> links) { evaluate(links); }
@Override
public Links<ID> topo() { return links; }
public void evaluate(Links<ID> links){
this.links = links; evaluate();
}
public void evaluate(){
degrees = getDegrees();
distances = getDistances();
summaryDist = getSummaryDistances(distances);
}

public int getDegree(){return getMax(degrees);}


public int getDiameter() {return getDiameter(distances);}
public double getMiddleDiameter(){return getMiddleDiameter(summaryDist);}
public double getTraffic(){return getTraffic(getMiddleDiameter(),
getDegree());}
public StringBuilder toStr(){return toStr("N;S;D;M;T;");}
public StringBuilder toStr(String template){
StringBuilder sb = new StringBuilder();
for (char c:template.toCharArray()) {
switch (c){
case 'N': {sb.append(links.getN()); break;}
case 'S': {sb.append(getDegree()); break;}
case 'D': {sb.append(getDiameter()); break;}
case 'M': {sb.append(getMiddleDiameter()); break;}
case 'T': {sb.append(getTraffic()); break;}
default: sb.append(c);
}
}
return sb;
}
public static <T> Collection<BufferedParametrizer<T>>
parametrizeAll(Collection<Links<T>> topos){
Collection<BufferedParametrizer<T>> res = new LinkedList<>();
for (Links<T> t: topos) {
res.add(new BufferedParametrizer(t));
}
return res;
}
public static <T> StringBuilder toStr(Collection<BufferedParametrizer<T>>
parametrizers,
String template,
String delim){
StringBuilder sb = new StringBuilder();
sb.append(template).append(delim);
for (BufferedParametrizer p:parametrizers) {
sb.append(p.toStr(template)).append(delim);
}
return sb;
}
}
public interface TopologyBuilder<ID> {Links<ID> build(Object... args);}
public interface CodeBuilder<ID extends Code> extends TopologyBuilder<ID> {
@Override
default Links<ID> build(Object... args) {
int rank = Operations.cast(args, 0, Integer.class, 2);
NumericSystem ns =
Operations.cast(args, 1, NumericSystem.class,
NSDefaults.NS_BIN);
return build(rank, ns, args);
}
Links<ID> build(int rank, NumericSystem ns, Object... args);
class HypercubeBuilder implements CodeBuilder<Code>{
@Override
public Links<Code> build(int rank, NumericSystem ns, Object... args)
{
return build(rank, ns);
}
public Links<Code> build(int rank, NumericSystem ns){
Collection<CodeSequence> sequences = ns.generateAll(rank);
Collection<Code> codes = Code.convert(sequences, ns);
Links<Code> links = new Topology<>(codes);
AllFunction.AF_Exchange exchange = new AllFunction.AF_Exchange();
for (Code code:codes) {
for (int i = 0; i < rank; i++) {
links.link(code, exchange.exec(code, i));
}
}
return links;
}
}
class DeBrujinBuilder implements CodeBuilder<Code>{
@Override
public Links<Code> build(int rank, NumericSystem ns, Object... args)
{
return build(rank, ns);
}
public Links<Code> build(int rank, NumericSystem ns){
Collection<CodeSequence> sequences = ns.generateAll(rank);
Collection<Code> codes = Code.convert(sequences, ns);
Links<Code> links = new Topology<>(codes);
AllFunction.AF_Shift shift = new AllFunction.AF_Shift();
for (Code code:codes) {
links.link(code, shift.exec(code));
}
return links;
}
}
}
public interface MultilevelBuilder<ID, ID1, ID2> extends TopologyBuilder<ID>{
@Override
default Links<ID> build(Object... args) {
Links<ID1> cluster = Operations.cast(args, 0, Links.class,
TopologiesDefaults.line);
Links<ID2> external = Operations.cast(args, 1, Links.class,
TopologiesDefaults.line);
return build(cluster, external, args);
}
Links<ID> build(Links<ID1> cluster, Links<ID2> external, Object... args);
}
public class LatSquareBuilder<ID extends Code> implements CodeBuilder<ID> {
@Override
public Links<ID> build(int rank, NumericSystem ns, Object... args) {
Integer[] cols;
List<CodeSequence> seq = new ArrayList<>();
seq.addAll(ns.generateAll(rank));
if (args != null) {
int len = args.length;
cols = new Integer[len - 2];
for (int i = 2; i < len; i++) {
cols[i - 2] = Operations.cast(args[i], Integer.class, 0);
}
}else{
cols = new Integer[]{1, seq.size()/2, seq.size()/4};
}
return buildLS((List<ID>) Code.convert(seq, ns), cols);
}
public Links<ID> buildLS(List<ID> sequence, Integer[] cols){
int len = sequence.size();
Links<ID> topo = new Topology<>(sequence);
Set<Integer> usedCols = new HashSet<>();
usedCols.add(0);
for (Integer col:cols) {
if (usedCols.contains(col)) continue;
for (int i = 0; i < len; i++) {
topo.link(sequence.get(i), sequence.get((i+col)%len));
}
usedCols.add(col);
}
return topo;
}
}
public abstract class CartesianProductBuilder<ID, ID1, ID2>
implements MultilevelBuilder<ID, ID1, ID2> {
public abstract ID getID(ID1 inner, ID2 outer, Links<ID1> cluster,
Links<ID2> external);
public Links<ID> createNew(Links<ID1> cluster, Links<ID2> external,
@NotNull HashMap<ID1, HashMap<ID2, ID>> map)
{
List<ID1> inners = cluster.getIDs();
List<ID2> outers = external.getIDs();
Links<ID> result = new Topology<>();
for (ID1 inner:inners) {
HashMap<ID2, ID> m = new HashMap<>();
for (ID2 outer:outers) {
ID id = getID(inner, outer, cluster, external);
m.put(outer, id);
result.add(id);

}
map.put(inner, m);
}
return result;
}
public void createLinks(Links<ID> topology,
Links<ID1> cluster,
Links<ID2> external,
HashMap<ID1, HashMap<ID2, ID>> map
){
List<ID1> inners = cluster.getIDs();
List<ID2> outers = external.getIDs();
for (int i = 0; i < inners.size()-1; i++) {
ID1 in1 = inners.get(i);
for (int j = 0; j < outers.size()-1; j++) {
ID2 out1 = outers.get(j);
ID id1 = map.get(in1).get(out1);
for (int k = i+1; k < inners.size(); k++) {
ID1 in2 = inners.get(k);
for (int l = j+1; l < outers.size(); l++) {
ID2 out2 = outers.get(l);
if (

((in1.equals(in2))&&(external.hasLink(out1, out2))) ||

((out1.equals(out2))&&(cluster.hasLink(in1, in2)))
){
ID id2 = map.get(in2).get(out2);
topology.link(id1, id2);
}
}
}
}
}
}

@Override
public Links<ID> build(Links<ID1> cluster, Links<ID2> external,
Object... args) {return build(cluster, external);}
public Links<ID> build(Links<ID1> cluster, Links<ID2> external){
HashMap<ID1, HashMap<ID2, ID>> map = new HashMap<>();
Links<ID> topo = createNew(cluster, external, map);
createLinks(topo, cluster, external, map);
return topo;
}
public static CartesianProductBuilder<Integer, Integer, Integer>
getIntBuilder(){
return new CartesianProductBuilder<Integer, Integer, Integer>(){
@Override
public Integer getID(Integer inner, Integer outer,
Links<Integer> cluster, Links<Integer> external) {return outer*cluster.getN()
+inner;}
};
}
public static CartesianProductBuilder<CodeSequence, CodeSequence,
CodeSequence> getCodeSeqBuilder(){
return new CartesianProductBuilder<CodeSequence, CodeSequence,
CodeSequence>(){
@Override
public CodeSequence getID(CodeSequence inner, CodeSequence
outer, Links<CodeSequence> cluster, Links<CodeSequence> external) {
return CodeSequence.concat(inner, outer);
}
};
}

public static CartesianProductBuilder<String, String, String>


getStringBuilder(){
return new CartesianProductBuilder<String, String, String>(){
@Override
public String getID(String inner, String outer, Links<String>
cluster, Links<String> external) {return outer+inner;}
};
}

public static <A, B> CartesianProductBuilder<Pair<A, B>, A, B>


getPairedBuilder(){
return new CartesianProductBuilder<Pair<A, B>, A, B>(){
@Override
public Pair<A, B> getID(A inner, B outer, Links<A> cluster,
Links<B> external) { return new Pair<>(inner, outer);}
};
}
}

You might also like