Compact way to represent a progress with many sub-operations?

I have the following type of progress:

(this is in text mode but the final representation will be in graphic mode)

enter image description here

Problem:

While this is a very detailed view of the current progress, it’s not really compact.

Generally, the representation of some progress is supposed to be compact, in this case it takes a non neglible portion of the screen.

Context:

This is for a video game where loading is pretty long and I would like to give a few information about what is being loaded, e.g. graphics, sounds, etc

Question:

I am looking for a more compact way to represent all these sub-operations, any suggestions?

Poisson Summation Formula for Square-Integrable Functions on Locally Compact Abelian Groups

The Poisson Summation Formula (PSF) is most often stated with the requirement that the functions in question be in $ L^{1}$ . However, after doing some searching, I found that there is a paper by R.P. Boas, Jr. which extends the PSF to square-integrable functions in the case of $ L^{2}\left(\mathbb{R}\right)$ . As such, I was wondering where I might be able to find a generalization of this result to functions defined on $ L^{2}\left(G\right)$ , where $ G$ is an arbitrary locally compact abelian group.

If it helps, I’m only really interested in the case where $ G$ is $ \mathbb{Q}$ or $ \mathbb{Q}/\mathbb{Z}$ —or, equivalently, their duals, $ \mathbb{A}$ (the $ \mathbb{Q}$ adeles) and $ \overline{\mathbb{Z}}$ (the profinite integers).

Amenability of the group of outer automorphisms of a connected compact Lie group

Forgive my ignorance on the Lie theory. I have the following questions in my current work concerning a certain property of compact connected Lie groups.

First, allow me to fix some notations. Let $ G$ be a connected compact Lie group, $ \mathfrak{g}$ its Lie algebra. Then $ \operatorname{Aut}(G)$ , the group of (smooth) automorphisms of the $ G$ , is a closed subgroup of $ \operatorname{Aut}(\mathfrak{g})$ , hence is a Lie group itself. Let $ \operatorname{ad} : G \to \operatorname{Aut}(G) \subseteq \operatorname{Aut}(\mathfrak{g})$ be the adjoint representation and denote its image by $ \operatorname{Inn}(G)$ , and needless to say, $ \operatorname{Inn}(G)$ is a normal subgroup of $ \operatorname{Aut}(G)$ . We denote the quotient group $ \operatorname{Aut}(G) / \operatorname{Inn}(G)$ by $ \operatorname{Out}(G)$ , and this is what I mean when I say the group of outer automorphisms in the title.

Question A. When $ \operatorname{Out}(G)$ is countable, is $ \operatorname{Inn}(G)$ always open in $ \operatorname{Aut}(G)$ ?

More generally, although this seems to have a higher chance to have a negative answer, one can ask the following question, which I suspect is still true:

Question B. Is $ \operatorname{Inn}(G)$ always open in $ \operatorname{Aut}(G)$ ? If Question A has an affirmative answer, this is equivalent to ask if $ \operatorname{Out}(G)$ is always countable.

Question C. When $ \operatorname{Inn}(G)$ is open in $ \operatorname{Aut}(G)$ , is $ \operatorname{Out}(G)$ (which now a countable discrete group) always amenable as a locally compact group?

A little experiment on the abelian case of the $ n$ -dimensional torus (in which case the inner automorphism group is trivial, and $ \operatorname{Aut}(T^n)$ is $ GL_n(\mathbb{Z})$ ), and the semisimple case (at least over $ \mathbb{C}$ instead of $ \mathbb{R}$ , which implies $ \operatorname*{Out}(G)$ being finite), seems to make a negative answer to the above questions not completely trivial. Although I am happy that the abelian case and the semisimple case already suffice for the purpose of my current work, which only needs $ \operatorname{Out}(G)$ to be amenable, I would be very interested if one can prove or disprove the amenability of $ \operatorname*{Out}(G)$ for a general compact connected Lie group $ G$ .

A uniform upper bound for Fredholm index of quasi Laplace operators on a compact parallelizable manifold

Assume that $ M$ is a compact parallelizable manifold. Is there an upper bound for the absolute value of Fredholm index of all operators in the form $ D=\sum_{i=1}^n \partial^2/\partial{X_i^2}$ where $ \{X_1,X_2,\ldots,X_n\}$ is a global smooth frame?

Machine learning, kNN and NB algorithm. Is there a way make the code more compact and nice looking?

So this is the task I am working on:

“In this assignment you will implement the K-Nearest Neighbour and NaĂ¯ve Bayes algorithms and evaluate them on a real dataset using the stratified cross validation method. You will also evaluate the performance of other classifiers on the same dataset using Weka. Finally, you will investigate the effect of feature selection, in particular the Correlation-based Feature Selection method (CFS) from Weka.”

I have done the weka part and also written seperate code for performance evaluation. Here, I need help with the main code where I am implementing kNN and NB algorithm.

Here is my code! I want to reduce the number of lines and possibly make it look more neat. Please help as much as you can. I have tried splitting into more functions and then calling them to do the work but is there a way I can do more? Also, is there a way the for loops can be written more compactly?

import heapq import sys import math as m from decimal import Decimal  class Entry:     def __init__(self, attributes):         self.attributes = attributes         self.diabetes = "yes" if "yes" in attributes else "no" if "no" in attributes else ""      def __str__(self):         string = ""         for attributeNum, attribute in enumerate(self.attributes):             if attributeNum == len(self.attributes) - 1:                 string += str(attribute)             else:                 string += str(attribute) + ','         return string      def set_ifdiabetes(self, diabetes):         self.diabetes = diabetes      def euclidean(self, other_entry):         sum = 0.0         for i in range(len(self.attributes)):                 sum += m.pow(float(self.attributes[i]) - float(other_entry.attributes[i]), 2)         return m.sqrt(sum)  class NB:     def __init__(self, training_data, testing_data):         self.training_data = training_data         self.testing_data = testing_data          self.training_entries = []         self.testing_entries = []          self.diabetes_yes = []         self.diabetes_no = []          self.mu_diabetesyes = []         self.mu_diabetesno = []          self.sigma_diabetesyes = []         self.sigma_diabetesno = []          self.num_attributes = 0          self.p_diabetesyes = 0         self.p_diabetesno = 0          self.num_diabetesyes = 0         self.num_diabetesno = 0      def train(self):         self.traincleandata()         self.get_mus()         self.get_sigmas()      def traincleandata(self):         for line in self.training_data:             if self.num_attributes == 0:                 self.num_attributes = len(line.split(','))                 for i in range(self.num_attributes):                     self.diabetes_yes.append([])                     self.diabetes_no.append([])                     self.mu_diabetesyes.append(0.0)                     self.mu_diabetesno.append(0.0)                     self.sigma_diabetesyes.append(0.0)                     self.sigma_diabetesno.append(0.0)             params = line.split(',')             cleanparams = getcleanparams(params)             entry = Entry(cleanparams)             self.training_entries.append(entry)              if (entry.diabetes == "yes"):                 for i in range(len(entry.attributes) - 1):                     self.diabetes_yes[i].append(Decimal(entry.attributes[i]))                 self.p_diabetesyes += 1                 self.num_diabetesyes += 1             else:                 for i in range(len(entry.attributes) - 1):                     self.diabetes_no[i].append(Decimal(entry.attributes[i]))                 self.p_diabetesno += 1                 self.num_diabetesno += 1          self.p_diabetesyes = Decimal(self.p_diabetesyes) / len(self.training_entries)         self.p_diabetesno = Decimal(self.p_diabetesno) / len(self.training_entries)      def get_mus(self):         for i in range(self.num_attributes - 1):             self.mu_diabetesyes[i] = sum(self.diabetes_yes[i]) / len(self.diabetes_yes[i])             self.mu_diabetesno[i] = sum(self.diabetes_no[i]) / len(self.diabetes_no[i])      def get_sigmas(self):          sigSumYes = [0] * self.num_attributes         sigSumNo = [0] * self.num_attributes          for i in range(self.num_attributes - 1):             for j in range(self.num_diabetesyes):                 sigSumYes[i] += m.pow(self.diabetes_yes[i][j] - self.mu_diabetesyes[i], 2)             self.sigma_diabetesyes[i] = m.sqrt(sigSumYes[i] / (len(self.diabetes_yes[i]) - 1))             for j in range(self.num_diabetesno):                 sigSumNo[i] += m.pow(self.diabetes_no[i][j] - self.mu_diabetesno[i], 2)             self.sigma_diabetesno[i] = m.sqrt(sigSumNo[i] / (len(self.diabetes_no[i]) - 1))      def test(self):         self.testcleandata()         self.testalgo()      def testcleandata(self):         for line in self.testing_data:             params = line.split(',')             cleanparams = getcleanparams(params)             entry = Entry(cleanparams)             self.testing_entries.append(entry)      def testalgo(self):         counter = 1         P_diabetesyes = [0] * self.num_attributes         P_diabetesno = [0] * self.num_attributes         for entry in self.testing_entries:             pYesEntry = 1             pNoEntry = 1             for i in range(self.num_attributes - 1):                 P_diabetesyes[i] = Decimal((1 / (self.sigma_diabetesyes[i] * m.sqrt(2 * m.pi))) * m.pow(m.e, (-m.pow(Decimal(entry.attributes[i]) - self.mu_diabetesyes[i], 2) / (2 * m.pow(self.sigma_diabetesyes[i], 2)))))                 P_diabetesno[i] = Decimal((1 / (self.sigma_diabetesno[i] * m.sqrt(2 * m.pi))) * m.pow(m.e, (-m.pow(Decimal(entry.attributes[i]) -self.mu_diabetesno[i], 2) / (2 * m.pow(self.sigma_diabetesno[i], 2)))))                 pYesEntry *= float(P_diabetesyes[i])                 pNoEntry *= float(P_diabetesno[i])              pYesEntry *= float(self.p_diabetesyes)             pNoEntry *= float(self.p_diabetesno)              entry.set_ifdiabetes("yes") if (pYesEntry/pNoEntry >= 1) else entry.set_ifdiabetes("no")             counter += 1  class kNN:     def __init__(self, training_data, testing_data, k):         self.k = k         self.training_data = training_data         self.testing_data = testing_data         self.training_entries = []         self.testing_entries = []      def __str__(self):         string_to_return = ''         for entry in self.training_entries:             string_to_return = string_to_return + str(entry) + '\n'         return string_to_return      def train(self):         for line in self.training_data:             params = line.split(',')             self.training_entries.append(Entry(getcleanparams(params)))      def test(self):         counter = 1         for line in self.testing_data:             params = line.split(',')             self.testing_entries.append(Entry(getcleanparams(params)))         for testEntry in self.testing_entries:             nearest = []             for trainEntry in self.training_entries:                 current_entry = (testEntry.euclidean(trainEntry), str(trainEntry.diabetes), str(trainEntry))                 nearest.append(current_entry)             heapq.heapify(nearest)             nearest.sort()             nearest = nearest[:int(self.k)]             num_diabetes = 0             for entry in nearest:                 if (entry[1] == "yes"):                     num_diabetes += 1             testEntry.set_ifdiabetes("yes") if (num_diabetes >= int(self.k)/2) else testEntry.set_ifdiabetes("no")             counter += 1      def compare(self):         for entry in self.testing_entries:             print("-----------")             print(entry.compare(self.training_entries[0]))             print(entry)             print(self.training_entries[0])   def getcleanparams(params):     params_nospaceortab = []     for param in params:         params_nospaceortab.append(param.strip())     return params_nospaceortab   if __name__ == '__main__':     training_file = open(sys.argv[1])     testing_file = open(sys.argv[2])     classifier_input = sys.argv[3]      training_lines = training_file.readlines()     training_cleanlines = getcleanparams(training_lines)      testing_lines = testing_file.readlines()     testing_cleanlines = getcleanparams(testing_lines)      if classifier_input == "NB":         classifier = NB(training_cleanlines, testing_cleanlines)         classifier.train()         classifier.test()         for entry in classifier.testing_entries:             print(entry.diabetes)     elif "NN" in classifier_input:         classifier = kNN(training_cleanlines, testing_cleanlines, (classifier_input.index('NN') - 1))         classifier.train()         classifier.test()         for entry in classifier.testing_entries:             print(entry.diabetes)     else:         print("Error: unknown classifier type")         sys.exit() 

Compact command line argument parser : Revisited

This question is a follow up to my previous one which can be found here. The user dfhwze suggested me to look into compiler construction and recommended me to write a lexer and a parser that would process the input step by step. I am very grateful that he pointed me into this direction, because I have the feeling everything is much more robust now. As this is my first time implementing a lexer and a parser I am convinced there are still things that can be optimized a lot.

A few things things that come to my mind:

  1. Are my naming conventions fine? Are all identifiers self-descriptive?
  2. Can I abstract the project more? I’d like it to be as flexible as possible.
  3. Are there performance optimizations that can be made?

Notes:

  1. Comma separated lists are intentionally processed as one argument.

To test the code run the unit tests (xUnit).

CommandLineLexer.cs

public class CommandLineLexer {     /// <summary>     /// To read a stream if characters     /// </summary>     private readonly TextReader _reader;      /// <summary>     /// The current token that is processed     /// </summary>     private CommandLineToken? _currentToken;      /// <summary>     /// Create a new lexer for an incoming character stream     /// </summary>     /// <param name="reader">The text reader that processes the data</param>     public CommandLineLexer(TextReader reader)     {         _reader = reader;     }      /// <summary>     /// Gets the next character in the stream     /// </summary>     /// <returns>Read the next character</returns>     private char ReadCharacter()     {         char c = (char) _reader.Read();         return c;     }      /// <summary>     /// Reads next CommandLineToken     /// </summary>     /// <returns>The next lexed token</returns>     public CommandLineToken Next()     {         var nextToken = Peek();         _currentToken = null;         return nextToken;     }      /// <summary>     /// Check next token but doesn't read it yet     /// </summary>     /// <returns>The next token</returns>     public CommandLineToken Peek()     {         if (_currentToken == null)             _currentToken = ReadNextToken();         return _currentToken.Value;     }      /// <summary>     /// Verifies if there are more character is the inputstream     /// </summary>     /// <returns>true if there are more characters, false if end of inputstream</returns>     public bool HasNext()     {         if (_currentToken == null)         {             SkipWhitespaces();             return _reader.Peek() != -1;         }          return true;     }      /// <summary>     /// Do not process whitespaces in the input unless they are part of an argument     /// </summary>     private void SkipWhitespaces()     {         while (true)         {             int c = _reader.Peek();             if (c == -1 || !char.IsWhiteSpace((char) c))                 break;             ReadCharacter();         }     }      /// <summary>     /// Read the next token     /// </summary>     /// <returns>The next lexed token</returns>     /// <exception cref="EndOfStreamException"></exception>     private CommandLineToken ReadNextToken()     {         SkipWhitespaces();          int peakedChar = _reader.Peek();         if (peakedChar == -1)             throw new EndOfStreamException(nameof(_reader));         char character = (char) peakedChar;          // Parsing Logic         switch (character)         {             case '-': return ReadSwitch();             case '"': return ReadQuotedArg();             case ',': return ReadCommaSeparator();             default:                 return ReadArg();         }     }      /// <summary>     /// Reads arguments that start and end with a quotionmark     /// </summary>     /// <returns>The lexed argument token</returns>     private CommandLineToken ReadQuotedArg()     {         var stringBuilder = new StringBuilder();          while (true)         {             stringBuilder.Append(ReadCharacter());             int chr = _reader.Peek();             if (chr == -1 || chr == '"')             {                 stringBuilder.Append("\"");                 ReadCharacter();                 break;             }         }          return new CommandLineToken(CommandLineTerminal.Argument, stringBuilder.ToString());     }      /// <summary>     /// Reads a comma separator token     /// </summary>     /// <returns>The lexed comma token</returns>     private CommandLineToken ReadCommaSeparator()     {         return new CommandLineToken(CommandLineTerminal.Comma, ReadCharacter().ToString());     }      /// <summary>     /// Reads an argument token     /// </summary>     /// <returns>The lexed comma token</returns>     private CommandLineToken ReadArg()     {         var stringBuilder = new StringBuilder();         var allowedChars = "abcdefghijklmonopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!:!?.".ToList();         while (true)         {             int chr = _reader.Peek();             if (chr == -1)                 break;             if (chr == ',' || chr == ' ')                 break;             if (!allowedChars.Contains((char) chr))                 throw new FormatException($  "Illegal character in argument");              stringBuilder.Append(ReadCharacter());         }          return new CommandLineToken(CommandLineTerminal.Argument, stringBuilder.ToString());     }      /// <summary>     /// Reads an argument token      /// </summary>     /// <returns>The lexed switch token</returns>     private CommandLineToken ReadSwitch()     {         var stringBuilder = new StringBuilder();         var allowedChars = "abcdefghijklmonopqrstuvxyz-".ToList();         while (true)         {             int chr = _reader.Peek();             if (chr == -1 || chr == ' ')                 break;             if (!allowedChars.Contains((char) chr))                 throw new FormatException($  "Illegal character in switch: {(char) chr}");              stringBuilder.Append(ReadCharacter());         }          if (stringBuilder.ToString().All(x => x == '-'))             throw new FormatException("Switch does not have a name");          return new CommandLineToken(CommandLineTerminal.Switch, stringBuilder.ToString());     } } 

CommandLineToken.cs

public struct CommandLineToken {     public CommandLineTerminal Terminal { get; }     public string Text { get; }      public CommandLineToken(CommandLineTerminal terminal, string text)     {         Terminal = terminal;         Text = text;     } } 

CommandLineTerminal.cs

public enum CommandLineTerminal {     /// <summary>     /// Switch     /// </summary>     Switch,      /// <summary>     /// Argument of a switch     /// </summary>     Argument,      /// <summary>     /// Separator for a list of arguments     /// </summary>     Comma, } 

CommandLineParser.cs

public class CommandLineParser {     /* Grammar:         *          * switches <- switch+         * switch <- SWITCH args         * args <- ARGUMENT (COMMA ARGUMENT)*         */      private readonly CommandLineLexer _lexer;      public CommandLineParser(CommandLineLexer lexer)     {         _lexer = lexer ?? throw new ArgumentNullException(nameof(lexer));     }      public CommandLineParser(TextReader reader)         : this(new CommandLineLexer(reader))     {     }      public CommandLineParser(string input)         : this(new StringReader(input))     {     }       public IEnumerable<CommandLineExpression> ParseAll()     {         var parsed = new List<CommandLineExpression>();         while (_lexer.HasNext())             parsed.Add(Parse());          return parsed;     }      private CommandLineExpression Parse()     {         var @switch = ExpectOneOf(CommandLineTerminal.Switch);          // Switch without args         if (!_lexer.HasNext())             return new CommandLineExpression(@switch.Text, null);          // Verify if there are more args after switch         while (true)         {             var next = _lexer.Peek();             switch (next.Terminal)             {                 case CommandLineTerminal.Switch:                     break;                 case CommandLineTerminal.Argument:                 {                     var allArgs = ParseAllArgs();                     return new CommandLineExpression(@switch.Text, allArgs);                 }                  default:                     throw new FormatException("Invalid character");             }         }     }      private IList<IArgument> ParseAllArgs()     {         var allArgs = new List<IArgument>();         while (true)         {             if (!_lexer.HasNext())                 return allArgs;              var next = _lexer.Peek();             switch (next.Terminal)             {                 case CommandLineTerminal.Switch:                     return allArgs;                 case CommandLineTerminal.Argument:                 {                     // Check if we are dealing with an ArgList                     var token = _lexer.Next();                      if (!_lexer.HasNext())                     {                         allArgs.Add(new CommandLineArgument(token.Text));                         return allArgs;                     }                      var next2 = _lexer.Peek();                      if (next2.Terminal == CommandLineTerminal.Comma)                     {                         var argList = ParseArgList(token);                         allArgs.Add(new CommandLineArgumentList(argList));                          break;                     }                      // Add arg normally - its not part of a list                     allArgs.Add(new CommandLineArgument(token.Text));                     break;                 }                  default:                     throw new FormatException("Invalid character");             }         }     }      private List<CommandLineArgument> ParseArgList(CommandLineToken token)     {         bool commaExpected = true;         var argList = new List<CommandLineArgument>() {new CommandLineArgument(token.Text)};         while (true)         {             if (!_lexer.HasNext())                 return argList;              var next = _lexer.Peek();              switch (@next.Terminal)             {                 case CommandLineTerminal.Switch:                 {                     return argList; // kk, new swithc starts we are done processing the arglist                 }                  case CommandLineTerminal.Argument:                 {                     if (commaExpected)                     {                         // end of arg list but there is more args that do not belong to the list                         return argList;                     }                      argList.Add(new CommandLineArgument(_lexer.Next().Text));                     commaExpected = true;                      break;                 }                  case CommandLineTerminal.Comma:                 {                     if (commaExpected)                     {                         commaExpected = false;                         // consume comma                         _lexer.Next(); // ??                         break;                     }                      throw new FormatException(); // two commas after each other?                 }             }         }     }      private CommandLineToken ExpectOneOf(params CommandLineTerminal[] terminals)     {         var token = _lexer.Next();         if (!terminals.Contains(token.Terminal))             throw new FormatException($  "Expected {string.Join(",", "terminals")}");         return token;     } } 

CommandLineExpression.cs

public class CommandLineExpression {     public string Switch { get; }     public IList<IArgument> Args { get; }      public CommandLineExpression(string @switch, IList<IArgument> args)     {         Switch = @switch;         Args = args;     }     // Can this be optimized?     public override bool Equals(object obj)     {         var cmp = obj as CommandLineExpression ?? throw new ArgumentNullException(nameof(obj));         if (Switch != cmp.Switch)             return false;          if (Args == null ^ cmp.Args == null)             return false;          if (Args == null && cmp.Args == null)             return true;          if (Args.Count != cmp.Args.Count)             return false;          for (var index = 0; index < Args.Count; index++)         {             // Verify if both args are arglists             if (Args[index] is CommandLineArgumentList)             {                 // Compare args and arglists too                 if (cmp.Args[index] is CommandLineArgumentList)                 {                     // Iterate arg lists of both args                     for (var index2 = 0; index2 < ((CommandLineArgumentList) Args[index]).Arg.Count; index2++)                     {                         var argListItem1 = ((CommandLineArgumentList) Args[index]).Arg[index2];                         var argListItem2 = ((CommandLineArgumentList) cmp.Args[index]).Arg[index2];                         if (argListItem1.Argument != argListItem2.Argument)                             return false;                     }                 }                 else                 {                     return false;                 }                  continue;             }              if (cmp.Args[index] is CommandLineArgumentList)             {                 // Compare args and arglists too                 if (Args[index] is CommandLineArgumentList)                 {                     // Compare args and arglists too                     for (var index2 = 0; index2 < ((CommandLineArgumentList) Args[index]).Arg.Count; index2++)                     {                         var argListItem1 = ((CommandLineArgumentList) Args[index]).Arg[index2];                         var argListItem2 = ((CommandLineArgumentList) cmp.Args[index]).Arg[index2];                         if (argListItem1.Argument != argListItem2.Argument)                             return false;                     }                 }                 else                 {                     return false;                 }                  continue;             }              // If argument is not a list do the normal comparison             var arg = (CommandLineArgument) Args[index];             var arg2 = (CommandLineArgument) cmp.Args[index];             if (arg.Argument != arg2.Argument)                 return false;         }          return true;     } } 

CommandLineArgumentList.cs

public class CommandLineArgumentList : IArgument {     public IList<CommandLineArgument> Arg { get; }      public CommandLineArgumentList(IList<CommandLineArgument> arg)     {         Arg = arg;     } } 

CommandLineArgument.cs

public class CommandLineArgument : IArgument {     public string Argument { get; }      public CommandLineArgument(string argument)     {         Argument = argument;     } } 

IArgument.cs

public interface IArgument { } 

Please be nitpicky in the review đŸ™‚

Recovery image without root functionality for an Xperia Z1 Compact

A friend of mines child has a Sony Xperia Z1 Compact and a lot of what I would call Criminal Energy (he proved that on several occasions).

Because he did a lot of stuff on his phone which he is not supposed to do, we want to prevent him of finding out how to boot into the previously installed TWRP Recovery Mode, where he could root his phone and do other uncool stuff.

From what I found out, I am not able to remove TWRP, but could totally replace it with something else.

So my question is, are there any simple, Backup/Restore only, no root option, no File editing (eg. build.props) Recovery images available for me to flash on that particular smartphone or do i have any other options? (We already installed and configured Family Link, but that of course does not prevent booting in recovery mode)

Compact command line argument parser

So, I decided to write my own little command line argument parser for various other projects I work on. I am aware that there are many good command line parser libraries, but I did wrote my own anyway (practice & implementation specific reasons).

The parser works fine, but I have a feeling that it can be improved a lot, mainly the following things come to mind

  1. Mainly the actual parser, CommandLineParser.cs. It seems very badly structured and I find it hard to read myself.
  2. Abstraction. I wonder if I can abstract it a bit more without making it a pain to use? Maybe by introducing some interfaces?
  3. Naming. I went with Option for the command line switch and with Value for the possible parameters. Are my methods/classes self-descriptive?
  4. Optimizations. I am sure there are segments that can be done more efficiently, mainly in CommandLineParser.ParseArguments(string[] args)

A couple of things to note:

  1. I’d like to keep the structure for the CommandLineValue.cs and CommandLineOption.cs mostly the same as they are part of a plugin architecture to communicate command line arguments between the plugins and the main application.
  2. No usage of Attributes to store the command line options.
  3. I did write a couple of unit tests to verify the parsers functionality. Despite them being not the main class to review, I am appreciate feedback there too đŸ™‚

Parser:

public class CommandLineParser {     /// <summary>     /// Defines all possible command line options the plugin can can process     /// </summary>     public List<CommandLineOption> SupportedOptions { get; }      /// <summary>     /// Initialize the commandline parser with a list of commandline options the plugin exposes     /// </summary>     /// <param name="supportedOptions"></param>     public CommandLineParser(List<CommandLineOption> supportedOptions)     {         SupportedOptions = supportedOptions;     }       /// <summary>     /// Parse the command line arguments and returns a list of commandline values that can be passed to the     /// plugin for further processing. The function also handles invalid amount and/or format of options, values     /// as well as missing required arguments etc     /// </summary>     /// <param name="args">The arguments to parse</param>     /// <returns>A list of parsed commandline values + options</returns>     /// <exception cref="InvalidCommandLineOptionException"></exception>     /// <exception cref="InsufficientCommandLineValuesException"></exception>     /// <exception cref="InvalidCommandLineValueException"></exception>     /// <exception cref="MissingRequiredCommandLineOptionException"></exception>     public IEnumerable<CommandLineValue> ParseArguments(string[] args)     {         var result = new List<CommandLineValue>();          if (args.Length == 0)             return Enumerable.Empty<CommandLineValue>();           // Process all command line arguments         for (int i = 0; i < args.Length; i++)         {             CommandLineOption option = null;             if (!IsSupportedOption(args[i], out option))                 throw new InvalidCommandLineOptionException($  "{args[i]} is not a valid command line option");              // Verify if the option expects additional values             if (HasAdditionalValues(option))             {                 // Check if enough additional values are given                 int additionalValues = option.ParameterTypes.Count;                 if (i + additionalValues + 1 > args.Length)                     throw new InsufficientCommandLineValuesException(                         $  "{args[i]} expects {additionalValues} values.");                  // Check if the additional values are in the right format                 // ToDo: Find more elegant solution                 var values = args.ToList().GetRange(i + 1, i + additionalValues).ToList();                 var types = option.ParameterTypes.ToList();                  var castedValues = values.Zip(types, (value, type) =>                 {                     try                     {                         return Convert.ChangeType(value, type);                     }                     catch                     {                         throw new InvalidCommandLineValueException(                             $  "Cannot cast between value {value} to type {type}");                     }                 });                  result.Add(new CommandLineValue(option, castedValues.ToList()));                  // Increase i to skip to the next option                 i += additionalValues;             }             else             {                 result.Add(new CommandLineValue(option, null));             }         }          // Collect required arguments         List<string> requiredOptions = new List<string>();         foreach (var option in SupportedOptions)         {             if (option.Required)                 foreach (var tag in option.Tags)                 {                     requiredOptions.Add(tag);                 }         }          // Check that no required arguments are missing (or occur twice)         var missing = GetMissingRequiredArgs<string>(requiredOptions, args.ToList());         if (missing == null)             return result;         throw new MissingRequiredCommandLineOptionException(             $  "The required arument(s) {string.Join(",", missing)} occured multiple times");     }      /// <summary>     /// Check that all required options are used and that they (the required options) dont occur multiple times are no duplicates     /// </summary>     /// <param name="required">A list of required options</param>     /// <param name="arguments"><The args to check</param>     /// <typeparam name="T">Any primitive type</typeparam>     /// <exception cref="MissingRequiredCommandLineOptionException">Thrown if any distinct required arguments exist more then once</exception>     /// <returns>A list of missing required args, if any. Null if none are missing.</returns>     static List<T> GetMissingRequiredArgs<T>(List<T> required, List<T> arguments)     {         // convert to Dictionary where we store the required item as a key against count for an item         var requiredDict = required.ToDictionary(k => k, v => 0);          foreach (var item in arguments)         {             if (!requiredDict.ContainsKey(item))                 continue;             requiredDict[item]++; // if we have required, adding to count             if (requiredDict[item] <= 1)                 continue;             throw new DuplicateRequiredCommandLineOptionException(                 $  "Required option {item} appeared more than once!");         }          var result = new List<T>();         // now we are checking for missing items         foreach (var key in requiredDict.Keys)         {             if (requiredDict[key] == 0)             {                 result.Add(key);             }         }          return result.Any() ? result : null;     }       /// <summary>     /// Verify if given option is part of the supported options     /// </summary>     /// <returns>true if the option is supported otherwise false</returns>     private bool IsSupportedOption(string optionIdentifier, out CommandLineOption option)     {         for (var index = 0; index < SupportedOptions.Count; index++)         {             var supportedOption = SupportedOptions[index];             if (supportedOption.Tags.Any(tag => tag == optionIdentifier))             {                 option = SupportedOptions[index];                 return true;             }         }          option = null;         return false;     }      /// <summary>     /// Indicates if a command line option has multiple values or if its just a flag     /// </summary>     /// <param name="option">Commandlineoption to check</param>     /// <returns>true if the option has multiple values, otherwise false</returns>     private bool HasAdditionalValues(CommandLineOption option)     {         var noParameters = option.ParameterTypes == null || option.ParameterTypes.Count == 0;         return !noParameters;     } } 

Classes to store commandline information:

public class CommandLineOption {     /// <summary>     /// The identifier of the commandline option, e.g. -h or --help     /// </summary>     public ICollection<string> Tags { get; }      /// <summary>     /// Description of the commandline option     /// </summary>     public string Description { get; }      /// <summary>     /// Indicates if the argument is optional or required     /// </summary>     public bool Required { get; }      /// <summary>     /// Types of the additional provided values such as directory paths, values etc ..     /// </summary>     public IList<Type> ParameterTypes { get; }      /// <summary>     /// Create a new true/false commandline option      /// </summary>     /// <param name="tags">Identifier of the command line option</param>     /// <param name="description">Description of the command line option</param>     /// <param name="required">Indicates if the command line option is optional or not</param>     public CommandLineOption(IEnumerable<string> tags, string description, bool required = false)     {         Tags = tags.ToList();         Description = description;         Required = required;     }      /// <summary>     /// Create a new true/false commandline option      /// </summary>     /// <param name="tags">Identifier of the command line option</param>     /// <param name="description">Description of the command line option</param>     /// <param name="required">Indicates if the command line option is optional or not</param>     public CommandLineOption(IEnumerable<string> tags, string description, bool required = false, params Type[] parameterTypes):         this(tags, description, required)     {         ParameterTypes = new List<Type>(parameterTypes);     }  } 
public class CommandLineValue : IEqualityComparer<CommandLineValue> {     /// <summary>     /// Holds all the values specified after a command line option     /// </summary>     public IList<object> Values { get; }      /// <summary>     /// The command line option the value(s) belong to     /// </summary>     public CommandLineOption Option { get; set; }      /// <summary>     /// Stores the values that correspond to a commandline option     /// </summary>     /// <param name="option">The commandline option the values refer to</param>     /// <param name="values">The values that are stored</param>     public CommandLineValue(CommandLineOption option, IList<object> values)     {         Option = option;         Values = values;     }       public bool Equals(CommandLineValue x, CommandLineValue y)     {         if (x.Option.Description == y.Option.Description &&             x.Option.Required == y.Option.Required &&             x.Option.Tags.SequenceEqual(y.Option.Tags) &&             x.Option.ParameterTypes.SequenceEqual(y.Option.ParameterTypes) &&             x.Values.SequenceEqual(x.Values))             return true;         return false;     }      public int GetHashCode(CommandLineValue obj)     {         return base.GetHashCode();     } } 

Custom Exception Classes:

public class DuplicateRequiredCommandLineOptionException : Exception {     public DuplicateRequiredCommandLineOptionException(string message) : base(message)     {     } }  public class InsufficientCommandLineValuesException : Exception {     public InsufficientCommandLineValuesException(string message) : base(message)     {     } }  public class InvalidCommandLineOptionException : Exception {     public InvalidCommandLineOptionException(string message) : base(message)     {     } }  public class InvalidCommandLineValueException : Exception {     public InvalidCommandLineValueException(string message) : base(message)     {     } }  public class MissingRequiredCommandLineOptionException : Exception {     public MissingRequiredCommandLineOptionException(string message) : base(message)     {     } } 

Unit Tests:

public class CommandLineParserTests {           [Fact]     public void ParseDuplicateRequiredArguments()     {         var args = new[] {"--randomize", "-o", "/home/user/Documents", "--randomize", "-d"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(                 new[] {"-r", "--randomize"},                 "Random flag",                 true),             new CommandLineOption(                 new[] {"-o", "--output-directory"},                 "Specifies the output directory",                 true,                 typeof(string)),             new CommandLineOption(                 new[] {"-d", "--dummy"},                 "Just another unused flag"),         };          var parser = new CommandLineParser(supportedOptions);         Assert.Throws<DuplicateRequiredCommandLineOptionException>(() =>             parser.ParseArguments(args)         );     }      [Fact]     public void ParseMissingRequiredArguments()     {         var args = new[] {"--randomize", "--output-directory", "/home/user/Documents"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(                 new[] {"-r", "--randomize"},                 "Random flag"),             new CommandLineOption(                 new[] {"-o", "--output-directory"},                 "Specifies the output directory",                 true,                 typeof(string)),             new CommandLineOption(                 new[] {"-d", "--dummy"},                 "Just another unused flag"),         };          var parser = new CommandLineParser(supportedOptions);         Assert.Throws<MissingRequiredCommandLineOptionException>(() =>             parser.ParseArguments(args)         );     }      [Fact]     public void ParseMatchingTypeCommandLineValues()     {         var args = new[] {"--log", "info", "1337", "3.1415"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(                 new[] {"-l", "--log"},                 "Logs info from exactly three data sources",                 false,                 typeof(string), typeof(int), typeof(float))         };          var parser = new CommandLineParser(supportedOptions);          var expectedValue = new CommandLineValue(new CommandLineOption(                 new[] {"-l", "--log"},                 "Logs info from exactly three data sources",                 false,                 typeof(string), typeof(int), typeof(float)),             new object[] {"info", 1337, (float) 3.1415});          var actualValue = parser.ParseArguments(args).ToList()[0];         Assert.True(expectedValue.Equals(actualValue, expectedValue));      }      [Fact]     public void ParseMismatchingTypeCommandLineValues()     {         var args = new[] {"--log", "info", "1337", "3.1415"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(                 new[] {"-l", "--log"},                 "Logs info from exactly three data sources",                 false,                 typeof(string), typeof(int), typeof(long)),         };         var parser = new CommandLineParser(supportedOptions);          Assert.Throws<InvalidCommandLineValueException>(() =>             parser.ParseArguments(args)         );     }      [Fact]     public void ParseInsufficientCommandLineValues()     {         var args = new[] {"-l", "info", "info2"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(                 new[] {"-l", "--log"},                 "Logs info from exactly three data sources",                 false, typeof(string), typeof(string), typeof(string)),         };         var parser = new CommandLineParser(supportedOptions);          Assert.Throws<InsufficientCommandLineValuesException>(() =>             parser.ParseArguments(args)         );     }      [Fact]     public void ParseInvalidCommandLineOption()     {         var args = new[] {"--force"};         var supportedOptions = new List<CommandLineOption>         {             new CommandLineOption(new[] {"-h", "--help"}, "Show the help menu"),         };         var parser = new CommandLineParser(supportedOptions);          Assert.Throws<InvalidCommandLineOptionException>(() =>             parser.ParseArguments(args)         );     }      [Fact]     public void ParseNoCommandLineOptions()     {         var args = new string[] { };         var parser = new CommandLineParser(null);         var result = parser.ParseArguments(args);          Assert.Equal(Enumerable.Empty<CommandLineValue>(), result);     } } 

I appreciate all suggestions. Feel free to be very nitpicky. đŸ™‚

Open subspaces of compact locally spectral spaces

By Prop. 16 of Hochster’s paper on spectral spaces we know that quasi-separated locally spectral spaces admit an open topological embedding into a spectral space. The question is what happens if we drop the quasi-separatedness hypothesis. Does there exist a locally spectral space that does not admit an open topological embedding into a compact locally spectral space?

Closed Poincaré dual is $\int_M \eta_S \wedge \omega $ and not $\int_M \omega \wedge \eta_S$. What about the compact Poincaré dual?

My book is Differential Forms in Algebraic Topology by Loring W. Tu and Raoul Bott of which An Introduction to Manifolds by Loring W. Tu is a prequel.

The characterization of the closed PoincarĂ© dual is given here (the “(5.13)”) in Section 5.5. This has $ \int_M \omega \wedge \eta_S$ , where $ \eta_S$ is on the right rather than left. The comments here confirm that this is a mistake.

I believe the characterization for the compact PoincarĂ© dual for compact $ S$ and $ M$ of finite type given here (the “(5.14)”) is correct with $ \eta_S’$ on the right. But since the “(5.13)” is a mistake, I think this may have some implications for the compact PoincarĂ© dual.

Bott and Tu say

If (5.14) holds for any closed k-form $ \omega$ , then it certainly holds for any closed k-form $ \omega$ with compact support. So as a form, $ \eta_S’$ is also the closed PoincarĂ© dual, i.e., the natural map $ H^{n-k}_c(M) \to H^{n-k} (M)$ sends the compact PoincarĂ© dual to the closed PoincarĂ© dual.

I think the quote implicitly references “(5.13)”. My question depends whether or not such thought is correct:

  1. If the quote implicitly references “(5.13)”, then what does the mistake of (5.13) mean for the claim that the compact PoincarĂ© dual is also the closed PoincarĂ© dual?

    • A. The claim is still correct and still for the same reason.

    • B. The claim is still correct but for a different reason.

    • C. The claim is now incorrect.

  2. If the quote does not implicitly reference “(5.13)”, then I’ve apparently misunderstood. How do Bott and Tu say compact PoincarĂ© dual is also the closed PoincarĂ© dual?