Δευτέρα 26 Δεκεμβρίου 2016

Γράφοι χωρίς συντεταγμένες.


Σε μια εργασία που είχα πρόσφατα για τεχνητή 
νοημοσύνη μας δίνονταν γράφοι με την εξής μορφή:
Μπορείτε να δείτε όλοκληρο το text εδώ

και έπρεπε να εμφανίζουμε το path από ένα αρχικό 
κόμβο σε έναν τελικό κόμβο δοκιμάζοντας
διάφορους αλγόριθμους αναζήτησης όπως ο A* , 
uniform cost , depth first search , breadth first search.

Οπότε μετά το πέρας της εργασίας απέκτησα το εξής ερώτημα:

-Πως θα μπορούσε κάποιος να απεικονήσει τους παραπάνω γράφους χωρίς να γνωρίζει λεπτομέρειες όπως συντεταγμένες.

Η αρχική ιδέα ήταν να δημιουργήσω ομογενείς κύκλους με κέντρο τον κόμβο που έχει ευρετικό 0. Άρα με βάση την ευρετική τιμή του κάθε κόμβου η ευρετική τιμή θα αποτελούσε την ακτίνα του κόμβου από το 0,0 όπου βρίσκεται ο κόμβος - στόχος αυτός που έχει ευρετικό 0.
Και για να μην είναι όλοι οι κόμβοι στην ίδια ευθεία πολύ απλά ο καθένας θα έχει γωνία: (count / πλήθος των κόμβων * 2π)
Όπου το count θα ξεκινάει από το 1 και θα ανεβαίνει κατα 1 για κάθε κόμβο. O κώδικας που χρησιμοποιήθηκε είναι της παρακάτω μορφής και έβγαζε έναν γράφο όπως αυτόν

-Τό πρόβλημα με το εξής σύστημα είναι ότι οι γραμμές και οι κόμβοι τέμνονται συχνά.

Η δεύτερη ιδέα είναι ξεκινόντας από έναν κόμβο να αρχίσεις να τοποθετείς γύρω του σε έναν κύκλο όλους τους γειτονικούς του κόμβους οι οποίοι δεν έχουν ήδη τοποθετηθεί .Η φόρμουλα των γωνιών του κύκλου είναι όμοια με την παραπάνω: (count / πλήθος των γειτονικών κόμβων * 2π)


-Το κακό είναι ότι αυτή η μέθοδος λειτουργεί μόνο για γράφους των οποίων ΌΛΟΙ οι κόμβοι είναι συνδεδεμένοι στον γράφο.

Σάββατο 16 Ιουλίου 2016

ΟΑΣΑ τηλεματική API documentation

Όπως πολλοί μπορεί να έχετε δει , εδώ και αρκετό ο Ο.Α.Σ.Α. έχει προσθέσει μια καινούργια τεχνολογία σε όλες τις στάσεις των λεωφορείων, μέσα από την οποία μπορεί να μάθει κάποιος σε πόση ώρα θα βρίσκεται στην στάση το λεωφορείο που περιμένει . Επίσης έχει δημιουργήσει μια εφαρμογή για android η οποία δείχνει live και τις τοποθεσίες των λεωφορείων .

Μου κάνει ένας συνάδελφος καθώς γυρνάμε από την βόλτα μας αν θα ηταν δυνατό να χρησιμοποιήσουμε και εμείς τα δεδομένα του Ο.Α.Σ.Α.για μια δικιάς μας εφαρμογή .

Ανοίγω λοιπόν το http://telematics.oasa.gr/ και ψάχνω να βρω όλα τα linked javascript αρχεία.
Βρίσκω λοιπόν μερικά jquery αρχεία και αυτό το link (http://telematics.oasa.gr/js/script.js).
Ψάχνωντας για το εξής string "$.ajax" βρίσκω όλα τα POST requests που κάνει το script στο http://telematics.oasa.gr/api/ και στην συνέχεια αφού διάβασα λίγο τον κώδικα έφτιαξα ένα unofficial documentation (http://oasa-telematics-api.readthedocs.io/en/latest/) .


Καλή επιτυχία σε ότι φτιάξετε, όσοι το χρησιμοποιήσετε και καλό καλοκαίρι .

P.S : Για όσους θέλετε να κάνετε contribute μπορείτε να κάνετε fork από το repo μου που βρίσκεται 
εδώ

Παρασκευή 24 Ιουνίου 2016

Python 3

Ήρθε ο καιρός για την μεγάλη απόφαση . Python 2 ή Python 3 ; 

Κατά την διάρκεια του fosscomm 2016 έκανα μια παρουσίαση σχετικά με ασύγχρονο προγραμματισμό . Στην παρουσίαση λοιπόν έθεσα το παραπάνω ερώτημα , και εξήγησα ότι η Python 3 προσφέρει σημαντικές δυνατότητες που δεν υπάρχουν στην Python 2.
Θεωρώ λοιπόν ότι πλέον δεν αξίζει τον κόπο να γράφω python2 & python3 οπότε προσωπικά
θα γράφω από εδώ και στο εξής μόνο σε python3 έτσι ώστε να μπορώ να απολαμβάνω όλες τις
δυνατότητες που προσφέρει η γλώσσα χωρίς να χρειάζεται να σκέφτομαι το αν θα λειτουργεί ο κώδικας και σε python2.

Στο branch stop-words του project Hurricane άρχισα να υποστηρίζω python3 για τις νέες εκδόσεις .
και άρχισα να σχεδιάζω νέα χαρακτηριστικά όπως
  • αφαίρεση από τα δεδομένα των λεγόμενων stop-words 
  • updated urls 
  • ο crawler θα σέβεται το robots.txt 
  • καλύτερη δομή κώδικα 

Μερικοί σημαντικοί σύνδεσμοι:
http://python3statement.github.io/
http://www.snarky.ca/why-python-3-exists
https://asmeurer.github.io/blog/posts/moving-away-from-python-2/

Δευτέρα 18 Απριλίου 2016

Fosscomm 2016

Στις 16 / 04 / 2016 είχα την τιμή να παρουσιάσω στο fosscomm 2016 στο πανεπιστήμιο του Πειραιά σχετικά με ασύγχρονο προγραμματισμό σε Python στο οποίο αναφέρθηκα στο asyncio. Κατα την διάρκεια της παρουσίασης μου ζητήθηκε να ανεβάσω την παρουσίαση και αν και ανέφερα ότι δεν θα τα ανεβάσω στο blog τελικά τα ανέβασα και εδώ just in case . 

Σύνδεσμοι :
Ένα μεγάλο ευχαριστώ για την παρουσία σας και την υποστήριξη σας !

Ευχαριστώ πολύ ,
Γιάννης Παπαϊωάννου

Τετάρτη 21 Ιανουαρίου 2015

Απώλεια δεδομένων (Python)

Τώρα πρόσφατα δουλεύω σε ένα web spider σε Python με Tornado. Αρχικά για όσους δεν γνωρίζουν τι είναι μια αράχνη στο Διαδίκτυο , είναι ένα bot (robot) το οποίο επισκέπτεται μια ιστοσελίδα μαζεύει όλα τα δεδομένα που βρίσκει και στην συνέχεια εκτελεί την ίδια διαδικασία στα links που έχει βρει στην σελίδα κατά την συλλογή των δεδομένων .

Σε τι χρησιμεύει όμως αυτό ; Εταιρίες όπως η Google έχουν τις αράχνες τους με τις οποίες συλλέγουν δεδομένα τα οποία παρουσιάζουν στον χρήστη όταν αναζητεί κάτι .

Περισσότερες πληροφορίες μπορούν να βρεθούν εδώ : http://en.wikipedia.org/wiki/Web_crawler

Το πρόβλημα, όμως στον crawler που γράφω εγώ , είναι ότι άνοιγε συνέχεια links και πολλές ιστοσελίδες μετά από αρκετά requests έπαυαν να ανταποκρίνονται και μου έδιναν 404 και 503 status codes με αποτέλσμα κάποια δεδομένα να χάνονται .

Δοκιμάζοντας μερικές εντολές στo shell της mongodb
>db.lists.count() 
1626 
>db.urls.count() 
4055
όπου οι lists είναι η συλλογή (δεδομένων-ιστοσελίδας) ενω urls η συλλογή των συνδέσμων στους οποίους είχε δοκιμαστεί να γίνει crawling παρατηρόυμε ότι έχουμε μια τεράστια απώλεια (> 1/2) . Το πρόβλημα το αντιμετώπισα προσθέτωντας ένα exception:

except urllib2.HTTPError: 
    if not (len(queue_item) > 2): 
        self.queue.put((self.current_url, self.depth, 1)) 

το οποίο προσθέτει το url πάλι στην σειρά και αυτή την φορά θα περιμένει 1 δευτερόλεπτο πριν το ανοίξει .

Δευτέρα 12 Ιανουαρίου 2015

Βελτιστιοποίηση (Python)

Πριν δυό βδομάδες δούλευα μαζί με ένα φίλο σχετικά με ένα log manager σε Python
και είχαμε το εξής πρόβλημα . Κάθε φορά που ένας χρήστης πατάει το refresh πρέπει να γίνεται ένα ajax get request το οποίο θα επιστρέφει τις αλλαγές που συνέβησαν στο αρχείο . 
Ο κώδικας ήταν ο εξής :


diffs = differ.compare(files_cache[file_name], log_file.read())
diff_l = [diff for diff in diffs if re.search(diff_regex, diff)]
file_diffs[file_name] = "".join(diff_l)

Ο οποίος έπαιρνε τις αλλαγές και τις σύγκρινε εάν ξεκινάνε με "+" ή " " :
Επειδή με το  difflib της python επιστρέφονται και οι γραμμές που δεν έχουν αλλάξει ο έλεγχος αυτός έπαιρνε γύρω στα 11 λεπτά .

Όμως κάποιος ο οποίος θα σκεφτόταν ότι ένα log αρχείο έχει ΜΟΝΟ additions γιατί λοιπόν να κάτσεις να το διαβάσεις όλο και να μην ξεκινήσεις από εκεί που σταμάτησες ;

file_diffs[file_name] = file_contents[len(files_cache[file_name]):]

Χρόνος εκτέλεσης : 0,0001 s